SpringCloud学习笔记(五)Nacos注册中心

5.Nacos注册中心

官网是这么介绍的:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。功能和上面提到的Eureka类似,Nacos支持几乎所有主流类型的服务发现、配置和管理:

  • Kubernetes Service
  • gRPC & Dubbo RPC Service
  • Spring Cloud RESTful Service

先看如何使用再讲原理:

5.1 安装

需要先从官网下载Nacos并启动Nacos Server:github

有两个需要注意的点

1.JAVA_HOME配置
image-20230630170347362
这里在环境变量里配置JAVA_HOME没用,得去startup.cmd文件中
image-20230630170811378
2.鉴权
在2.2.1版本的Nacos需要手动配置secret.key,否则启动会报错,secret.key随便生成一串≥32位的字符串即可。(我这次下载2.2.2版本已经不需要配置鉴权也可以正常使用了,但是不需要登录,访问Nacos还是会提示开启鉴权)
image-20230630194149890

Windows

启动命令(standalone代表着单机模式运行,非集群模式):

 startup.cmd -m standalone

启动成功后从给出的url访问,账号密码都是Nacos

image-20230403192258672

5.2 服务注册

Eureka注册中心配置时,需要在server和client分别引入pom坐标并配置yml文件,Nacos除了这些还多了一个步骤,因为Nacos是spring-cloud-alibaba的依赖,所以需要先在父工程引入阿里巴巴依赖。

注意引入的版本要和spring-cloud兼容,参考版本说明

1.父工程pom文件引入坐标

 <properties>
     <!--指定版本-->
  <spring-cloud-alibaba.version>2022.0.0.0-RC1</spring-cloud-alibaba.version>
 </properties>
 <!--为了使用Nacos-->
 <dependencyManagement>
     <dependencies>
         <dependency>
             <groupId>com.alibaba.cloud</groupId>
             <artifactId>spring-cloud-alibaba-dependencies</artifactId>
             <version>${spring-cloud-alibaba.version}</version>
             <type>pom</type>
             <scope>import</scope>
         </dependency>
     </dependencies>
 </dependencyManagement>

我使用的spring-boot版本是3.0.5,spring-cloud版本是2022.0.2,所以要注意spring-cloud-alibaba的版本和这些兼容。Idea的Maven提示版本是你之前安装过的repository里的版本不一定对应,可以去maven官网查一下。

2.子工程client端pom文件引入Nacos依赖

  <!--Nacos客户端依赖包-->
 <dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-Nacos-discovery</artifactId>
 </dependency>

3.子工程yml文件配置Nacos

 spring:
  cloud:
    Nacos:
      server-addr: localhost:8848 # Nacos服务地址

4.配置文件

 spring.cloud.nacos.server-addr=127.0.0.1:8848

参考官方文档

注意:⭐

因为ribbon已经逐渐被spring-cloud弃用,改用loadBalancer,所以RestTemplate方法使用@LoadBalanced注解时无法使用ribbon负载均衡,需要手动引入loadBalancer的依赖才能正常解析user-service.在服务消费者的pom中添加其坐标即可.

 <!--2022版spring-cloud-alibaba必须添加这个依赖,否则域名解析不正确,找不到服务地址
             参考:https://blog.csdn.net/weixin_43887184/article/details/124036205-->
 <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-loadbalancer</artifactId>
 </dependency>

5.3 服务发现

1542119181336-b6dc0fc1-ed46-43a7-9e5f-68c9ca344d60

步骤:

1.pom中添加nacos-discovery依赖

2.application.yml中添加nacos服务地址

3.Spring Cloud原生注解@EnableDiscoveryClient开启服务注册发现功能

 @MapperScan("cn.itcast.user.mapper")
 @SpringBootApplication
 @EnableDiscoveryClient
 public class UserApplication {
     public static void main(String[] args) {
         SpringApplication.run(UserApplication.class, args);
    }
 }

4.服务消费者的RestTemplate添加@LoadBalanced注解

 @Bean
 @LoadBalanced
 public RestTemplate restTemplate() {
     return new RestTemplate();
 }

依然可以直接调用RestTemplate进行访问,但要注意返回值类型处理:

 //OrderService.java
  public Order queryOrderById(Long orderId) {
         // 1.查询订单
         Order order = orderMapper.findById(orderId);
         if (null!=order && null!= order.getUserId()){
             String url = URL_PREFIX+order.getUserId();
             //⭐注意:这里拿到的不是User类型而是Result类型,所以需要提取一下
             Result result = restTemplate.getForObject(url, Result.class);
             assert result != null;
             //将hashmap转成json再转成实体类对象
             ObjectMapper mapper = new ObjectMapper();
             User user = mapper.convertValue(result.getData(),User.class);
             order.setUser(user);
            }
         return order;
    }

5.3.1 Nacos服务分级存储模型

image-20230405171716846

设置集群属性:

 spring.cloud.Nacos.discovery.cluster-name: BJ

Nacos注册结果如下:

image-20230405174649645
微服务调用优先访问本地集群

eg.BJ的order-service优先调用BJ的user-service

默认是轮询调用,所以需要配置负载均衡规则

旧版SpringCloud仍然使用ribbon,所以可以通过如下方式配置:

 # 设置负载均衡,优先访问本地集群
 user-service:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.Nacos.ribbon.NacosRule

但我使用的项目是2022版的SpringCloud,以及启用了ribbon,所以使用新的方法配置负载均衡

 spring:
  application:
    name: order-service
  cloud:
    loadbalancer:
     # 使用Nacos做负载均衡,默认优先访问本地集群,默认使用随机方式访问服务
      Nacos:
        enabled: true
    Nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: BJ
根据权重负载均衡

直接在Nacos注册中心(localhost:8848)修改微服务权重,权重范围在0-1之间.

image-20230405203522034

这样Nacos就会控制优先访问权重更大的微服务. 如果权重为0则不会被访问,方便版本升级修改等,不需要重启。

5.3.2 环境隔离-namespace

一般实际开发中,可能会用到生产环境、开发环境切换等情况,可以使用环境隔离方便切换。

image-20230405204655733
  • 进入浏览器Nacos控制台,新建命名空间,复制id并在java项目中配置
image-20230405205331347

配置文件中添加命名空间

 spring:
  cloud:
    Nacos:
      discovery:
        cluster-name: BJ
        namespace: 2823f44e-dfec-4276-990c-8062646b9b13 # dev环境

成功image-20230405205847903

⭐注意:namespace用来做环境隔离,不同namespace下的服务不可见

group:group是一个次于namespace的隔离概念,属于弱隔离,主要用于逻辑区分一些服务使用场景或不同应用的同名服务,eg同一个服务的测试分组和生产分组.

5.3.3 Nacos注册中心原理

image-20230405210508000
Nacos和Eureka对比
  • 相同
    • 都支持服务注册和拉取
    • 都支持服务提供者心跳方式做健康检测
  • 区别
    • Nacos支持服务端主动检测提供者状态:临时实例和Eureka类似,采用心跳模式(Nacos更快),若无心跳则删掉实例;非临时实例,由注册中心定时询问,若无响应则等待实例恢复而非直接从注册中心删掉.
    • Nacos和Eureka都有一个服务缓存列表,服务消费者调用服务时就不需要每次都请求注册中心了. 服务缓存列表根据定时Pull更新.
    • 若服务提供者实例出现故障,则Nacos会立即通过push方式推送给服务消费者,避免服务缓存列表更新不及时消费者访问到故障微服务.Eureka没有这个即时通知机制.
    • Nacos集群默认采用AP方式(强调数据可用性),当集群中存在非临时实例时采用CP模式(强调数据可靠性和一致性);Eureka采用AP方式
    • Eureka主要关注服务注册和服务发现,Nacos除了这两者之外还提供了配置管理功能,支持集中式配置和动态推送,无需重启服务.
    • Nacos提供服务命名空间和分组概念,使得服务可以按照业务、环境等进行划分和隔离.

设置Nacos实例为临时实例的方式:修改yml文件

 spring:
  cloud:
    Nacos:
      discovery:
      # false则为非临时实例,默认值为true
        ephemeral: true

5.4 Nacos配置管理

作用:统一配置;配置更改热更新

5.4.1 统一配置

1.Nacos中添加配置信息,为了防止命名冲突,DataID命名一般采用形式:[服务名称]-[profile].[后缀名],后缀支持yaml和properties.

image-20230406102837320

2.因为部分配置信息写在了Nacos中,所以需要先读取Nacos的yaml配置,与本地yml合并后创建spring容器进行后续内容.因此需要先拿到Nacos的地址才能获取Nacos配置文件,就需要在比application.yml优先级更高的bootstrap.yml文件中给出Nacos地址.

image-20230406103401592

3.Nacos服务器刚刚新建配置的service(user-service)的pom引入Nacos配置管理客户端依赖 

<dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-Nacos-config</artifactId>
 </dependency>

4.在resource目录下添加bootstrap.yml引导文件,其优先级高于application.yml 

spring:
  application:
    name: user-service
  profiles:
    active: dev # 环境
  cloud:
    Nacos:
      server-addr: localhost:8848 #Nacos地址
      config:
        file-extension: yaml # 文件后缀名
image-20230406104558053

5.删掉application.yml中与bootstrap.yml重复的配置

6.注意springcloud2020已经弃用bootstrap方式(,所以要想继续使用,需要在对应service的pom文件中引入bootstrap依赖

注意

bootstrap是系统级的资源配置文件,是用在程序引导执行时更加早期配置信息读取;application是用户级的资源配置文件,是用来后续的一些配置所需要的公共参数.bootstrap.yml比application.yml优先级更高. 可能会覆盖掉application的配置,不够优雅? 
<!--使用bootstrap
     但是官方已经弃用了,所以不建议使用|-->
 <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-bootstrap</artifactId>
 </dependency>

7.⭐采用springcloud最新的配置中心文件的引入方式根据官方文档,可以直接在application.yml中添加配置,不需要重建bootstrap文件.image-20230406145644430

但是官网给出的配置方案报错

 java.lang.IllegalStateException: Unable to load config data from 'optional:configserver:http://localhost:8848'

通过搜索发现,可以使用另一种配置方法:

 spring:
  config:
    import:
     # 注意格式(-后面要有空格,optional可以不写,其实-也可以不写,这是列表形式,只有一个参数时可以省略),冒号后面直接写配置文件名称即可
      - optional:Nacos:user-service-dev.yaml
 # 除此之外,把bootstrap.yml的配置信息写在application.yml中即可.

5.4.2 热更新

实现热更新还需要进一步配置,有两种方法

1.在@Value注入的变量所在类上添加注解@RefreshScopeimage-20230406202756172

2.使用@ConfigurationProperties注解

@Component
 @Data
 @ConfigurationProperties(prefix="pattern")
 public class PatternProperties{
     private String dateformat;
 }然后在需要使用的地方直接调用即可: @Slf4j
 @RestController
 //@RefreshScope
 @RequestMapping("/user")
 public class UserController {
 ​
 ​
     @Autowired
     private PatternProperties patternProperties;
 //   @Value("${pattern.dateformat}")
 //   private String dateformat;
 ​
     @GetMapping("/now")
     public String now(){
         return LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternProperties.getDateformat()));
    }
 }

5.4.3 多环境配置共享

image-20230406204501225

所以Nacos服务器新建一个user-service.yaml放置多环境共享的配置,使用方式同上.

优先级:[spring.application.name]-[spring.profiels.active].yaml>[spring.application.name].yaml>本地application.yml

5.4.4 Nacos集群搭建

如图:Nacos生产环境下一定要部署为集群方式

image-20230406205102197
模拟Nacos集群:

官方参考文档进入Nacos的conf目录,修改配置文件cluster.conf.example,重命名为cluster.conf:

然后添加内容:

 127.0.0.1:8845
 127.0.0.1.8846
 127.0.0.1.8847

配置Nacos数据库

Nacos使用时是需要配置数据库以便记录Nacos运行信息的,而数据库创建由Nacos官方文档给出创建方式,我直接复制了黑马的建表语句结果添加Nacos配置时报了发布失败的错误,因为黑马用的是低版本的Nacos所以不可用,我们需要用匹配版本,有两种获取资源方式:

  • 官网集群部署说明,注意要在分支中选择对应版本的sql源文件image-20230407210231620
  • 直接使用Nacos/conf/mysql-schema.sql,这个文件的内容和通过官网获取到的sql语句源文件一致,新建一个名为Nacos的数据库,将其加载到数据库中,创建出Nacos所需的表.此后使用Nacos会自动向表中填入数据.
image-20230407210813280

然后修改application.properties文件,添加数据库配置,db.url.0的数据库名称即为上面导入Nacos数据库的库名.

 spring.datasource.platform=mysql
 ​
 db.num=1
 ​
 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=root72760

此后对Nacos的操作都会记录在Nacos数据库的对应表内,例如添加Nacos服务器的配置文件后数据库记录如下:

image-20230407211410463
image-20230406211343993

之后分别启动三份Nacos(集群启动cluster)

 startup.cmd

注意:启动Nacos集群时会发现,接口之间会相互占用导致启动失败,原因如下,官方文档

image-20230407153536195
原始端口884588468847
+1000984598469847
+1001984698479848

所以无论这三个Nacos节点以什么顺序启动,都会有端口被占用而无法启动,做法就是端口间隔至少为2,改成8845 8847 8849.

nginx配置集群:

进入nginx的conf/nginx.conf文件在http中添加如下配置:

 http {
    # config for Nacos cluster
    upstream Nacos-cluster{
        server 127.0.0.1:8845;
        server 127.0.0.1:8847;
        server 127.0.0.1:8849;
    }
    server{
        listen 80;
        server_name localhost;
 ​
        location /Nacos{
            proxy_pass http://Nacos-cluster
        }
 }

注意:因为Nacos多了个rGpc的通信方式,所以还需要配置rgpc的端口,即端口转发,所以还需要在nginx.conf文件中添加如下配置,需要注意的是顺序一定不能错!stream在http下方!!!

Nacos2_port_exposure.png
 http {
  ...
 }
 # Nacos集群的nginx配置
 stream {
    upstream Nacos-cluster-tcp {
    # 都加上1000的偏移量
        server 10.28.221.178:9845;
        server 10.28.221.178:9847;
        server 10.28.221.178:9849;
    }
    server {
    # Nacos 80+1000
        listen 1080;
        proxy_pass Nacos-cluster-tcp;
    }
 }

监听80端口时记得把配置文件中nginx的默认监听注释掉,否则会出现以下警告:

image-20230407194848853

打开nginx

 start nginx.exe

启动后访问Nacos可以看到集群后的节点列表:

image-20230407195442658

注册服务:需要在idea的项目中把Nacos服务器端口改为nginx中配置的端口号80

image-20230406225016655

注意:这个时候还没有建立Nacos服务端的配置文件,所以idea中引用Nacos的配置会造成appication启动失败,先把引用的部分注释掉就好了:

image-20230407195925349

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注