微服务注册中心中间件--nacos 快速入门

按照个人的习性,分布式我学习完以后一定会忘为此写次笔记自己快速复习 注册中心作为开启为微服务的第一站真的常看常新

目录

  1. Springcloud介绍
  2. 注册中心–Eureka
  3. 注册中心–Nacos

Springcloud介绍及微服务介绍

  • 为什么学?
    也不是以前的单体架构被淘汰而是,当业务足够大型,进行优化

单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部署。
在这里插入图片描述

优点:

  1. 架构简单
  2. 部署成本低

缺点:

耦合度高(维护困难、升级困难)

所以就要对传统单体项目进行优化,而分布式就是很好的方式

分布式架构

分布式架构:根据业务功能对系统做拆分,每个业务功能模块作为独立项目开发,称为一个服务。
在这里插入图片描述

分布式架构的优缺点:

优点:

  • 降低服务耦合
  • 有利于服务升级和拓展

缺点:

  • 服务调用关系错综复杂

分布式架构虽然降低了服务耦合,但是服务拆分时也有很多问题需要思考:

  • 服务拆分的粒度如何界定?
  • 服务之间如何调用?
  • 服务的调用关系如何管理?

人们需要制定一套行之有效的标准来约束分布式架构。

微服务

微服务的架构特征:

  • 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责
  • 自治:团队独立、技术独立、数据独立,独立部署和交付
  • 面向服务:服务提供统一标准的接口,与语言和技术无关
  • 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题

在这里插入图片描述
微服务的上述特性其实是在给分布式架构制定一个标准,进一步降低服务之间的耦合度,提供服务的独立性和灵活性。做到高内聚,低耦合。

因此,可以认为微服务是一种经过良好架构设计的分布式架构方案
任何分布式架构都离不开服务的拆分,微服务也是一样。

服务拆分原则

这里我总结了微服务拆分时的几个原则:

  • 不同微服务,不要重复开发相同业务
  • 微服务数据独立,不要访问其它微服务的数据库
  • 微服务可以将自己的业务暴露为接口,供其它微服务调用

但方案该怎么落地?选用什么样的技术栈?全球的互联网公司都在积极尝试自己的微服务落地方案。

其中在Java领域最引人注目的就是SpringCloud提供的方案了。

Springcloud

SpringCloud是目前国内使用最广泛的微服务框架。官网地址:https://spring.io/projects/spring-cloud。

SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验。
其中常见的组件包括:
在这里插入图片描述
完整的微服务框架,所需中间件
在这里插入图片描述

通过docker容器部署
在这里插入图片描述

SpringCloud底层是依赖于SpringBoot的,并且有版本的兼容关系需要到官网查看
在这里插入图片描述
所以接下来快速复习各个中间件的使用

注册中心 Eureka,nacos

什么是注册中心呢,百度定义

“注册中心的作用一句话概括就是存放和调度服务,实现服务和注册中心,服务和服务之间的相互通信。注册中心可以说是微服务架构中的”通讯录“,它记录了服务和服务地址的映射关系.

现在建立俩个服务端(user,order)作为微服务部分演示,俩者具有不同的数据库,但是俩个微服务数据具有关联,为此暴露接口完成交互,勇主持中心演示

演示微服务demo

user部分

实体类

@Data
public class User {
    private Long id;
    private String username;
    private String address;
}

业务层

@Service
public class UserService {

//    @Autowired
    @Resource
    private UserMapper userMapper;

    public User queryById(Long id) {
        return userMapper.findById(id);
    }
}

mapper数据层

@Mapper
public interface UserMapper {
    
    @Select("select * from tb_user where id = #{id}")
    User findById(@Param("id") Long id);
}

controller暴露接口,给其他服务使用

@RestController
@RequestMapping("/user")
// @RefreshScope
public class UserController {

    @Autowired
    private UserService userService;


    /**
     * 路径: /user/110
     *
     * @param id 用户id
     * @return 用户
     */
    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id,
                          @RequestHeader(value = "Truth", required = false) String truth) {
        System.out.println("truth: " + truth);
        return userService.queryById(id);
    }
}

order部分

Controller

简单的通过路由查询订单信息
@RestController
@RequestMapping("order")
public class OrderController {

   @Autowired
   private OrderService orderService;

    @GetMapping("{orderId}")
    public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
        // 根据id查询订单并返回
        return orderService.queryOrderById(orderId);
    }
}

实体类排pojo

@Data
public class Order {
    private Long id;
    private Long price;
    private String name;
    private Integer num;
    private Long userId;
    private User user;
}

注意这里的user实体类俩个服务不同数据库,故此需要多个服务完成交互,先申明user尸体

@Data
public class User {
    private Long id;
    private String username;
    private String address;
}

由于order服务需要向另一个微服务交互,为此引入交互工具,restemplate,springmvc自带注入bean即可
任一配置类

@Bean

public RestTemplate restTemplate() {
    return new RestTemplate();
}

service服务层

@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;
@Autowired
    RestTemplate restTemplate;
//    @Autowired
//    private UserClient userClient;
//根据另一个服务端暴露的接口,发送请求完成
    public Order queryOrderById(Long orderId) {
   url="http://localhost:8082/user/"+order.getUserId().toString();
        User user=restTemplate.getForObject(url, User.class);
        order.setUser(user);
        // 4.返回
        return order;
    }
}


上述在服务调用关系中,会有两个不同的角色:

服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)

服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)

但是,服务提供者与服务消费者的角色并不是绝对的,而是相对于业务而言。

如果服务A调用了服务B,而服务B又调用了服务C,服务B的角色是什么?

  • 对于A调用B的业务而言:A是服务消费者,B是服务提供者
  • 对于B调用C的业务而言:B是服务消费者,C是服务提供者

因此,服务B既可以是服务提供者,也可以是服务消费者

并且order服务中,如要获取另一服务的数据,所以需要俩个微服务端进行交互,以上代码是通过rest风格解决完成交互
但是有以下缺点

  • url地址是硬编码,ip,和端口信息需要写死
  • 无法检查各个服务间的安全状态,如果发生宕机且多个服务,那么后果不堪设想
  • 如果仅使用源生的HTTP完成交互,那么每个服务都需要维护其他服务的地址信息,并且这些地址信息还可能会发生变化。这会使得服务之间的通信变得复杂,可能导致某些服务无法通过传统方式进行通信

为此使用注册中心管理微服务中的各个服务,接下来进行使用注册中心优化服务交互

Eureka

百度百科:Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。

主要作用:

在这里插入图片描述
服务向注册中心注册,消费端拉取提供端的服务,提供端会进行定时心跳续约机制如果时间内没有收到回应,注册中心就就会选择另一个服务提供者进行服务

搭建Eureka服务端
  1. 新建一个maven工程,springboot项目,引入Eureka服务端依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
  1. @EnableEurekaServer开启开关 开启服务端
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args


        );
    }
}

3.配置服务端

server:
  port: 10086 # 服务端口
spring:
  application:
    name: eurekaserver # eureka的服务名称
eureka:
  client:
    service-url:  # eureka的地址信息  应该是配置集群,用逗号间隔开来 erueka(注册中心)本身也是微服务
      defaultZone: http://127.0.0.1:10086/eureka

eureka本身也是服务之一,所以也需要配置客户端( client:)需要配置服务名字和端口,以及defaultZone地址信息
打开游览器游览,instances是注册的服务,目前只有服务器本身在这里插入图片描述

客户端

对原来的服务进行注册使其变为客户端

1.导入注册端客户依赖

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

2.配置客户端

application:
   name: userserive//也需要写清楚,用户注册信息的服务名
eureka:
   client:
   service-url:  # eureka的地址信息
   defaultZone: http://127.0.0.1:10086/eureka 这样客户端项目启动起来的时候会向该地址发送注册信息

然后启动类添加客户端注解
@EnableEurekaClient
3.启动成功后再次访问服务端web页面

在这里插入图片描述
此时看到被注册成功

演示服务交互

上述列子中改写俩者的,服务消费者和提供者通样注册以后,服务交互改为以下,可以直接使用服务名进行拉取交互,无需写ip

 String url="http://userservice/user/"+order.getUserId().toString();
        User user=restTemplate.getForObject(url, User.class);
        order.setUser(user);

其中可以配置负载均衡

  1. 消费端服务在注入rest工具时可以使用@LoadBalanced注解选择赋值负载均衡
    PS:这种影响是全局的,服务消费端和任意服务端之间的负载均衡准寻这种规则

添加负载均衡器的依赖
pom

  <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
            <version>3.1.0</version>
        </dependency>
    @Bean
    @LoadBalanced
    //负载均衡当出现多个同名服务根据算法选择
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    /**
     *
     * @return 改变规则IRule的子类改变赋值均衡的子类
     */
//   @Bean
//    public IRule randomRule() {
//        return new RandomRule();
//    }
  1. 配置类中进行指定服务提供者的负载均衡规则
userservice: #对应服务的名称
  ribbon:
 #   NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
     负载均衡规则userservice: #对应服务的名称
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则

原理:
在这里插入图片描述
在这里插入图片描述
不同规则的含义如下:

内置负载均衡规则类规则描述
RoundRobinRule简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。
AvailabilityFilteringRule对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的..ActiveConnectionsLimit属性进行配置。
WeightedResponseTimeRule为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。
BestAvailableRule忽略那些短路的服务器,并选择并发数较低的服务器。
RandomRule随机选择一个可用的服务器。
RetryRule重试机制的选择逻辑

懒加载

Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。

而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

ribbon:
  eager-load:
    enabled: true # 开启饥饿加载
    clients: # 指定饥饿加载的客户端服务名称
     userservice

nacos

国内公司一般都推崇阿里巴巴的技术,比如注册中心,SpringCloudAlibaba也推出了一个名为Nacos的注册中心。相较于源生Nacos 相比 Eureka,提供了更多的功能特点:

和Eureka不同的是,nacos的启动方式是通过下载

  1. GitHub的Release下载页:https://github.com/alibaba/nacos/releases

  2. Nacos的默认端口是8848,如果你电脑上的其它进程占用了8848端口,请先尝试关闭该进程。如果无法关闭占用8848端口的进程,也可以进入nacos的conf目录,修改配置文件中的端口:

  3. 启动非常简单,进入bin目录,结构如下:

进入cmd界面: 输入以下指令启动单机模式

startup.cmd -m standalone

也可以docker进行安装

docker 安装

当然也可以使用安装docker,环境隔离方便卸载

  • 在虚拟机或服务器创建对应文件夹,便于以后修改什么配置
    在这里插入图片描述
  • 拉取对应镜像
docker pull nacos/nacos-server:1.2.0

运行创建容器

docker run --env MODE=standalone --name nacos --restart=always  -d -p 8848:8848 nacos/nacos-server:1.2.0
  • MODE=standalone 单机版

  • –restart=always 开机启动

  • -p 8848:8848 映射端口

  • -d 创建一个守护式容器在后台运行

localhost:8848/nacos
注意

初始账号密码就是nacos,服务端配置好以后就开始配置服务客户端
上面是1.x的版本2.x之后是如下,需要多暴露一些端口

docker run --name nacos-server \
-p 8848:8848 \
-p 7848:7848 \
-p 9848:9848 \
-p 9849:9849 \
--privileged=true \
--restart=always \
-e JVM_XMS=256m \
-e JVM_XMX=256m \
-e MODE=standalone \
-e PREFER_HOST_MODE=hostname \
-v /mydata/nacos/logs:/home/nacos/logs \
-d nacos/nacos-server:v2.2.0

https://sca.aliyun.com/docs/2022/overview/version-explain/ 一定要看版本说明!!!微服务光是配置就一大段

1)引入依赖

在cloud-demo父工程的pom文件中的<dependencyManagement>中引入SpringCloudAlibaba的依赖:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>2.2.6.RELEASE</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

然后在user-service和order-service中的pom文件中引入nacos-discovery依赖:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

注意:不要忘了注释掉eureka的依赖。

2)配置nacos地址

在user-service和order-service的application.yml中添加nacos地址:

spring:
  cloud:
    nacos:
      server-addr: localhost:8848

注意:不要忘了注释掉eureka的地址

3)重启

重启微服务后,登录nacos管理页面,可以看到微服务信息:
在这里插入图片描述
黄色健康不正常
在这里插入图片描述
此时服务消费者和服务提供者已经向注册中心发起注册

服务分级

通常会在分布式听到类似集群等概念,这就设计到服务分级
一个服务功能可以由工作室几个工作室实现,而工作室中又有很多工作成员

(1级 :业务)服务->->(二级 :计算机组合 )集群->(3级:某台计算机服务器本身)实列
将服务分部到不同分组,保障不宕机,服务安全,先访问本地集群的服务,如果其中的实列宕机,在访问其他集群的服务

在这里插入图片描述

微服务互相访问时,应该尽可能访问同集群实例,因为本地访问速度更快。当本集群内不可用时,才访问其它集群。例如:
在这里插入图片描述
杭州的集群中当访问统集群的服务宕机时候,就会访问同服务的其他集群

配置集群
userservice

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: HZ # 集群名称

配置负载均衡:

	#修改order-service的application.yml文件,修改负载均衡规则:


#因为底层是ribbon 所以不配置就是ribbon默认规则(轮训)
userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则 

``
创建多个实列,不同集群

不会idea创建多个实列的看这里:点击右上角配置,编辑配置,选择需要的服务点击复制,或者ctrl +d,vm选项输入 -Dserver.port=和复制源不同的端口 (-D项配置开头)启动实列

在这里插入图片描述
此时服务间发起交互,消费者会优先选择同一集群的服务提供者,当选择另一集群时说明,该集群下服务宕机,控制台报错,此时消费者orderservice向userservice发起交互,统集群下的实列无法访问,则访问其他集群,控制台警告跨集群

A cross-cluster call occurs,name = userservice, clusterName = HZ, instance = [Instance{instanceId='10.36.128.27#8086#SH#DEFAULT_GROUP@@userservice'

访问服务名

切换nacos权重在nacos管理界面切换

  • 当多个实列重复完成功能,一般希望将大部分请求给配置好的服务器,响应速度快,只有小请求会到处理能力较弱的服务器
  • 另一个常用功能就是服务升级,进行服务停机升级,权重设置小一点,限制用户访问端,平滑升级获取bug
  • 权重为0则完全不能访问,同集群权重越高访问概率越高

在这里插入图片描述

环境隔离

Nacos提供了namespace来实现环境隔离功能。

  • nacos中可以有多个namespace
  • namespace下可以有group、service等
  • 不同namespace之间相互隔离,例如不同namespace的服务互相不可见
  1. nacos服务端创建namespace 不创建默认public,id默认uuid

在这里插入图片描述3. nacos客户端服务yaml文件设置命名空间,并且重启

nacos:
server-addr: localhost:8848 #配置注册中心地址
discovery:
cluster-name: HZ #代指集群1杭州
namespace: 83efd19a-f0a1-4775-8106-2ad88fa47d97 #填写命名空间id 

启动
在这里插入图片描述
此时在访问该nacos客户端服务
就没办法和不同命名空间的服务交流

在这里插入图片描述值得注意的是注册和服务发现俩个模块都有环境隔离,配置文件中要注意

  cloud:
    nacos:
      server-addr: 192.168.249.133:8848
      discovery:
        namespace:  39bcf6xxxxxbc-e65xxxx6-4560-b211-d58bcac2b5fe #填写命名空间id
      config:
        file-extension: yaml
        namespace: 39bcf6bc-e656-4560-b211-d58bcac2b5fe

nacos和eureka区别

macos原理细节:消费者定时从注册中心拉取一次服务列表,减少服务端压力,然后再通过负载均衡选择不听的服务端,服务提供者也会每隔一段时间发起心跳检查供给注册中心检查健康状态(nacos间隔短一些),但是也有明显的不同.

  • nacos有个临时实列,和Eureka一样的检查,如果注册中心未检查到心跳,则会进行下线.而非临时实列是由注册中心主动向服务发起健康检查,就算挂掉也不会剔除下线,而是等着恢复正常
  • 另一个区别在于消费者,消费者定时拉取服务,Eureka也采取定时拉取,但是拉取期间如果服务提供端宕机后,会等到服务恢复才进行消费业务,而nacos采用push推送和pull主动变更消息的形式,每隔时间推送消息,如果服务提供端挂了,nacos会有消息推送的功能,会提前让消费者更换服务

配置上诉提到的临时队列

停掉,orderservice,当服务宕机时候,注册中心会直接让服务下线

默认是临时配置文件,进行申明为非临时配置文件

spring:
  cloud:
    nacos:
      server-addr: localhost:8848 #配置注册中心地址
      discovery:
        cluster-name: HZ #代指集群1杭州
        namespace: 83efd19a-f0a1-4775-8106-2ad88fa47d97 #填写id
        ephemeral: false  #是否临时队列 默认
#nacos的配置文件ephemeral属性表示配置实例是否为临时实例。当配置实例为临时实例时,如果该实例所在的nacos节点宕机或者被摘除,该实例会自动被删除。这种临时实例的特性可以用于实现一些短时任务或者临时节点的注册。

默认是零时队列
在这里插入图片描述

此时停掉该服务,nacos迅速发现服务状态变化,主动询问(速度快),但是并没有下线服务

nacos配置管理

nacos配置管理

nacos除了能够作为服务的注册中心管理服务,还可以管理配置

  • 如果微服务的配置文件和数个服务有关
  • 或者一个配置文件导致数个服务关联,那么带来的耦合度是极其高

通过nacos配置服务管理,可以实现多配置文件管理,以及热更新,(配置文件发生改变服务不需要重启)

实际操作

  1. 在nacos官网,点击新建配置,dataID就是文件名,一般命名名称服务名称-profile(配置环境),介绍和分组默认
  2. 命名规则(规范很重要,根据名字匹配):
    服务名-环境.yaml 在这里插入图片描述
  3. nacos的配置文件是做热更新的,一般是配置文件,写什么功能的开关,application项目本身的配置不能修改,点击发布
  4. 微服务拉取配置,需要先写一个bootstrap.yml的配置文件,来申明nacos地址,因为在nacos读取服务设计到一个启动流程问题
    项目启动->读取本地配置文件->创建spring容器->加载bean,现在由于在application,前就会拉取配置文件nacos,然后才会读取本地文件,所以需要先写一个bootstrap.yml的配置文件申明nacos地址(优先级更高)

微服务要拉取nacos中管理的配置,并且与本地的application.yml配置合并,才能完成项目启动。
但如果尚未读取application.yml,又如何得知nacos地址呢?
因此spring引入了一种新的配置文件:bootstrap.yaml文件,会在application.yml之前被读取,流程如下

在这里插入图片描述

  1. 引入nacos配置管理依赖
  <!--nacos的配置管理依赖, 使用该依赖nacos客户端的服务才能够被nacos服务端管理配置-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

写bootstrap配置之前,由于版本兼容性问题,有些版本无法识别bootstrap配置,可以添加以下配置

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-bootstrap</artifactId>
       <version>4.0.3</version>
    </dependency>

6.在bootstrap配置配置拉取的文件,和nacos地址(nacos的相关配置都可以写到改文件)
bootstrap.yml

spring:
  application:
    name: userservice  #决定数据源id
  profiles:
    active: dev # 环境
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos注册地址
      config:
        file-extension: yaml # 文件后缀名

controller

@Slf4j
@RestController
//@RefreshScope

@RequestMapping("/user")
// @RefreshScope
public class UserController {

    @Autowired
    private UserService userService;
//验证是否拉取到nacos配置
     @Value("${pattern.dateformat}")
     private String dateformat;
//
    @Autowired
    private PatternProperties properties;

    @GetMapping("prop")
    public PatternProperties properties(){
        return properties;
    }

    @GetMapping("now")
    public String now(){
        log.info("配置文件修改:源{}",properties.getName());
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(properties.getDateformat()));
//        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat));
    }

    /**
     * 路径: /user/110
     *
     * @param id 用户id
     * @return 用户
     */
    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id,
                          @RequestHeader(value = "Truth", required = false) String truth) {
        System.out.println("truth: " + truth);
        return userService.queryById(id);
    }
}

此时controller需要返回配置类,而我们定义配置类没有配置文件注入,所以用于验证是否能读取nacos配置文件

@Data
@Component //注册为组件
@ConfigurationProperties(prefix = "pattern")
public class PatternProperties {
    private String dateformat;
    private String envSharedValue;
    private String name;
}

配置文件
在这里插入图片描述
访问游览器路由
在这里插入图片描述
读取成功

服务通用配置

当有些配置实当前服务的所有实列通用的,那么只需要写
服务名.yaml文件命名即可
在这里插入图片描述

配置优先级

当以上的配置文件出现重复,哪个配置文件的优先级高呢

本地 远端 远端通用的优先级

远端环境>>远端通用>>本地,服务一启动,向nacos注册中心注册服务,所以远程>本地,详细的权限更高

实现热更新

nacos配置文件变更后,微服务无需重启就可以感知,不过使用到配置的地方需要下面俩种配置:

  • 在@value(使用该配置)富所在类上添加注解@RefreshScope,
  • 使用@configurationProperties注解

此时配置文件发送修改,自动刷新配置

配置共享

多环境共享,开发生产的环境是一样用到该配置项,如果每个服务的实列的配置文件都要用到该配置,环境发生改变,其环境配置文件也要相应改变很麻烦,于是配置文件共享就显得极其重要

nacos命名的环境配置

  • 项目服务名-环境.yaml 如 userservice-dev.yaml
  • 服务.yaml userservice.yaml 明显第二种和服务有关,是环境通用的

此时使用dev环境,和test环境都能够读取userservice环境的内容,实现了内容共享

日志信息

Located property source: [BootstrapPropertySource {name=‘bootstrapProperties-userservice-test.yaml,DEFAULT_GROUP’}, BootstrapPropertySource {name=‘bootstrapProperties-userservice.yaml,DEFAULT_GROUP’}, BootstrapPropertySource {name=‘bootstrapProperties-userservice,DEFAULT_GROUP’}]

配置优先级

当以上的配置文件出现重复,哪个配置文件的优先级高呢

本地 远端 远端通用的优先级

远端环境>>远端通用>>本地,服务一启动,向nacos注册中心注册服务,所以远程>本地,详细的权限更高

搭建集群

官方方给出的Nacos集群图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YeY5RA0v-1682331268982)(assets/image-20210409210621117.png)]

其中包含3个nacos节点,然后一个负载均衡器代理3个Nacos。这里负载均衡器可以使用nginx。

在这里插入图片描述

三个nacos节点的地址:

节点ipport
nacos1192.168.150.18845
nacos2192.168.150.18846
nacos3192.168.150.18847

2.搭建集群

搭建集群的基本步骤:

  • 搭建数据库,初始化数据库表结构
  • 下载nacos安装包
  • 配置nacos
  • 启动nacos集群
  • nginx反向代理

2.1.初始化数据库

Nacos默认数据存储在内嵌数据库Derby中,不属于生产可用的数据库。

官方推荐的最佳实践是使用带有主从的高可用数据库集群

这里我们以单点的数据库为例来讲解。

首先新建一个数据库,命名为nacos,而后导入下面的SQL:

CREATE TABLE `config_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(255) DEFAULT NULL,
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  `app_name` varchar(128) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  `c_desc` varchar(256) DEFAULT NULL,
  `c_use` varchar(64) DEFAULT NULL,
  `effect` varchar(64) DEFAULT NULL,
  `type` varchar(64) DEFAULT NULL,
  `c_schema` text,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_info_aggr   */
/******************************************/
CREATE TABLE `config_info_aggr` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(255) NOT NULL COMMENT 'group_id',
  `datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
  `content` longtext NOT NULL COMMENT '内容',
  `gmt_modified` datetime NOT NULL COMMENT '修改时间',
  `app_name` varchar(128) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';


/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_info_beta   */
/******************************************/
CREATE TABLE `config_info_beta` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL COMMENT 'content',
  `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_info_tag   */
/******************************************/
CREATE TABLE `config_info_tag` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  `tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_tags_relation   */
/******************************************/
CREATE TABLE `config_tags_relation` (
  `id` bigint(20) NOT NULL COMMENT 'id',
  `tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
  `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  `nid` bigint(20) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`nid`),
  UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = group_capacity   */
/******************************************/
CREATE TABLE `group_capacity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
  `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
  `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = his_config_info   */
/******************************************/
CREATE TABLE `his_config_info` (
  `id` bigint(64) unsigned NOT NULL,
  `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `data_id` varchar(255) NOT NULL,
  `group_id` varchar(128) NOT NULL,
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL,
  `md5` varchar(32) DEFAULT NULL,
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `src_user` text,
  `src_ip` varchar(50) DEFAULT NULL,
  `op_type` char(10) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  PRIMARY KEY (`nid`),
  KEY `idx_gmt_create` (`gmt_create`),
  KEY `idx_gmt_modified` (`gmt_modified`),
  KEY `idx_did` (`data_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';


/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = tenant_capacity   */
/******************************************/
CREATE TABLE `tenant_capacity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
  `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
  `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';


CREATE TABLE `tenant_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `kp` varchar(128) NOT NULL COMMENT 'kp',
  `tenant_id` varchar(128) default '' COMMENT 'tenant_id',
  `tenant_name` varchar(128) default '' COMMENT 'tenant_name',
  `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
  `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
  `gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
  `gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';

CREATE TABLE `users` (
	`username` varchar(50) NOT NULL PRIMARY KEY,
	`password` varchar(500) NOT NULL,
	`enabled` boolean NOT NULL
);

CREATE TABLE `roles` (
	`username` varchar(50) NOT NULL,
	`role` varchar(50) NOT NULL,
	UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
);

CREATE TABLE `permissions` (
    `role` varchar(50) NOT NULL,
    `resource` varchar(255) NOT NULL,
    `action` varchar(8) NOT NULL,
    UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
);

INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);

INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');

这个SQL文件
nacos下载后解压的目录中可以找到
在这里插入图片描述

2.2.下载nacos

nacos在GitHub上有下载地址:https://github.com/alibaba/nacos/tags,可以选择任意版本下载。

本例中才用1.4.1版本:

2.3.配置Nacos

将这个包解压到任意非中文目录下,如图:
在这里插入图片描述

目录说明:

  • bin:启动脚本
  • conf:配置文件

进入nacos的conf目录,修改配置文件cluster.conf.example,重命名为cluster.conf:(以下是我自己的ipv4地址)

在这里插入图片描述

然后添加内容:
ipv4

127.0.0.1:8845
127.0.0.1.8846
127.0.0.1.8847

然后修改application.properties文件,添加数据库配置

spring.datasource.platform=mysql

db.num=1
#改为自己的ipv4
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=123

2.4.启动

将nacos文件夹复制三份,分别命名为:nacos1、nacos2、nacos3

然后分别修改三个文件夹中的application.properties,

nacos1:

server.port=8845

nacos2:

server.port=8846

nacos3:

server.port=8847

然后分别启动三个nacos节点:

startup.cmd

2.5.nginx反向代理

官网下载

修改conf/nginx.conf文件,配置如下:

upstream nacos-cluster {
# 服务地址,填写之前的ipv4
    server 127.0.0.1:8845;
	server 127.0.0.1:8846;
	server 127.0.0.1:8847;
}

server {
# 返向代理的端口
    listen       488;
    server_name  localhost;

    location /nacos {
        proxy_pass http://nacos-cluster;
    }
}

而后在浏览器访问:http://localhost:488/nacos即可。

代码中application.yml文件配置如下:

spring:
  cloud:
    nacos:
      server-addr: localhost:488 # Nacos负载均衡的集群位置

完整配置文件

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;
#三个nacos结点负载均衡
upstream nacos-cluster {
    server 127.0.0.1:8845;
	server 127.0.0.1:8846;
	server 127.0.0.1:8847;
}


#测试nacos集群反向代理  nginx一个服务就是一个server
server {
    listen       1111;
    server_name  localhost;
#     服务的默认路径
    location /nacos {
    #     没有目录的root定位位置的时候proxy_pass反向代理就是直接转发到nacos集群
        proxy_pass http://nacos-cluster; #转发到刚才部署的集群
    }
}

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       8077;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html/dist;
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

此时游览器访问我们监听的端口就会被转发到nginx集群
在这里插入图片描述

此时nacos注册中心的服务就搭建好了,那么我们的服务就向注册中心进行注册,之前是注册单一结点,现在注册这个集群在这里插入图片描述
在nacos集群端新建一个配置文件,这里建立共享配置
在这里插入图片描述
打开数据库可以发现在这里插入图片描述

此时添加的nacos配置文件,就被nacos持久化到数据库了

2.6.优化

  • 实际部署时,需要给做反向代理的nginx服务器设置一个域名,这样后续如果有服务器迁移nacos的客户端也无需更改配置.

  • Nacos的各个节点应该部署到多个不同服务器,做好容灾和隔离

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
xxl-job-nacos 是一个基于微服务的调度系统。它的设计理念是通过将大型应用拆分成多个微服务,每个微服务都有一个独立的调度器,用于管理该微服务的任务调度和执行。xxl-job-nacos 使用 Nacos 作为注册中心,通过 Nacos 实现微服务的注册和发现。 通过将任务调度设置为微服务的一部分,xxl-job-nacos 可以实现任务的集中管理和分布式部署。它提供了一套友好的调度管理界面,用于配置和监控任务的运行情况。用户可以通过该界面添加、编辑和删除任务,指定任务的执行时间和频率。同时,xxl-job-nacos 支持任务的动态调度,可以实时修改任务的执行策略和参数,以适应不同的业务需求。 通过使用 Nacos 作为注册中心,xxl-job-nacos 实现了任务的注册和发现。当一个新任务被添加到调度系统中时,它会通过 Nacos 将任务的信息注册到注册中心,并通知相应的微服务微服务通过订阅注册中心的信息,获知新任务的相关信息,并根据任务的调度策略和配置进行任务的执行。当任务执行完成后,微服务会将执行结果反馈给 xxl-job-nacos,并更新任务状态和日志。 总的来说,xxl-job-nacos 是一个基于微服务的调度系统,它通过将任务调度设置为微服务的一部分,实现了任务的集中管理和分布式部署。同时,xxl-job-nacos 使用 Nacos 作为注册中心,实现了任务的注册和发现,以实时更新任务的信息和执行结果。通过这样的设计,xxl-job-nacos 可以提供强大的任务调度能力,适用于大型应用的任务调度和分布式执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝胖子不是胖子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值