Nacos 注册中心是什么?如何使用?

Nacos 的配置中心的使用我们已经了解👉使用 SpringBoot 连接 Nacos 配置中心实现配置的热更新 - 掘金 (juejin.cn) ,本篇介绍如何使用 Nacos 的注册中心。

一、Nacos 注册中心

注册中心通常有两个角色。

  • 服务提供者(生产者):对外提供服务的微服务应用,将自己的服务地址注册到注册中心,以供消费者发现和调用。
  • 服务调用者(消费者):调用其它微服务的应用程序,向注册中心订阅自己需要的服务,并基于服务提供者注册的信息发起远程调用。

(一)生产者实现

这里假设你已经知道如何创建多模块项目。(如何创建?👉构建强大的 Spring Boot 多模块项目:一步步指南 - 掘金 (juejin.cn)

  1. 将服务注册到 Nacos

创建一个 SpringBoot 多模块项目,在父模块的pom文件中添加以下依赖:

xml 复制代码
<!--   Spring MVC     -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>


<!--    注册中心依赖    -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
  1. 创建两个子模块,分别在配置文件中(application.yml)设置 Nacos 服务端信息
yml 复制代码
#配置 nacos 注册中心
spring:
  application:
    name: nacosRegisterDemo1 #服务名称
  cloud:
    nacos:
      discovery:
      	# Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Naco 服务器主机和端口
        server-addr: localhost:8848
        username: nacos
        password: nacos

#动态端口号,子模块的端口号
server:
  port: 0

分别在子模块中创建一个测试接口

java 复制代码
@RestController
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/getname")
    public String getNameById(Integer id){
        return "lishi-"+id;
    }
}
  1. 启动 Nacos 服务、运行两个子模块,打开 Nacos 控制台http://localhost:8848/nacos/index.html。

点击"详情":

可以看到每个子模块的ip+端口信息,可以根据ip、端口来访问接口(这不是重点)。

(二)消费者实现

注册中心消费者的实现要复杂一些,消费者要调用生产者的HTTP接口,需要引入SpringCloudOpenFeign进行HTTP调用(构造HTTP请求来调用生产者的接口);为了实现负载均衡,还要添加客户端负载均衡器SpringCloudLoadBalancer。这里的消费者,就是一个模块调用其它模块的服务(接口),就好比用浏览器来调用后端接口一样。这样做是来看看模块间是如何通信的。

  1. 添加如下依赖到父模块的pom.xml
xml 复制代码
<!--    负载均衡器    -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!--   微服务架构中服务之间的调用 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. 创建一个子模块consumer当作消费者
  1. 配置 Nacos 服务信息(在consumer中的pom.xml
yml 复制代码
spring:
  application:
    name: nacosRegisterDemo1
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        username: nacos
        password: nacos
        register-enabled: false #表示不需要注册到注册中心
server:
  port: 8080 #消费者需要一个固定端口
  1. 在启动类上添加@EnableFeignClients注解,用来开启OpenFeign
java 复制代码
@SpringBootApplication
@EnableFeignClients    //开启 OpenFeign
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
}
  1. 编写 OpenFeign调用代码,创建一个UserService用来测试
java 复制代码
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Service
@FeignClient("nacosRegisterDemo1") //表示调用 nacos 中的 nacosRegisterDemo1 服务
public interface UserService {
    /**
     * 调用"nacosRegisterDemo1服务中生产者的 /user/getname 接口,该接口为:根据id 获取姓名"
     * @param id
     * @return
     */
    @RequestMapping("/user/getname")
    String getNameById(@RequestParam("id") Integer id);//@RequestParam 一定不能省略。在使用OpenFeign进行服务间通信时,需要使用@RequestParam注解来明确指定哪个方法参数应该绑定到哪个HTTP请求参数。
}

@FeignClient("")里的内容一定要跟 Nacos 中的服务名一致。

@RequestMapping("")中的url要跟待调用的生产者模块中的url相同,跟单体项目前端调用后端时的url一样。

  1. 调用Openfeign接口代码
java 复制代码
@RestController
public class BusinessController {

    @Autowired
    private UserService userService;
    
    @RequestMapping("/getnamebyid")
    public String getNameById(Integer id){
        return userService.getNameById(id);
    }
}

此时我有两个生产者(子模块)pro_1pro_2,它们的测试接口:

pro_1:

java 复制代码
@RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/getname")
    public String getNameById(Integer id){
        return "lishi-"+id+"-pro_1";
    }
}

pro_2:

java 复制代码
@RestController
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/getname")
    public String getNameById(Integer id){
        return "lishi-"+id+"-pro_2";
    }
}

现在在浏览器中输入http://localhost:8080/getnamebyid?id=1它就会调用 nacosRegisterDemo1 服务中生产者的"/user/getname"接口,但是pro_1pro_2url是一样的,那返回的到底是哪一个值呢?我们直接全部启动,然后访问http://localhost:8080/getnamebyid?id=3

好像访问的是pro_1难道真是这样吗?再刷新一次:

又访问了pro_2了。因为在使用OpenFeign进行服务间通信时,默认的负载均衡策略是轮询调用。这意味着,如果服务集群中有多个实例提供了同一个接口,OpenFeign会依次将请求分发到每个实例上,每个实例都有平等的机会被调用。这种方式可以确保所有的服务实例都能得到均匀的负载,避免了某些实例被过度使用而其他实例空闲的情况。

(OpenFeign以及LoadBalancer负载均衡等详细的内容后续会更新,本篇只是演示注册中心的使用方法以及作用)

(三)注册中心的交互流程

看完上面一巴拉的文字可能还是有一点蒙,不过没关系,下面用图来描述整个过程。

上面的pro_1pro_2就相当于服务提供者,它们都注册到了Nacos的注册中心。接着consumer(消费者)也把自己注册到注册中心,这时它可以拉取服务列表,看到有哪些服务提供者,从而调用该服务(通过OpenFeign来调用)。

(四)注册中心参数说明

  1. 分组 :注册服务所在的组名,默认为 DEFAULT_GROUP,可以在配置文件中spring.cloud.nacos.discovery.group=groupName来设置。

  2. 保护阈值:健康节点要求的最小百分比。保护阈值应设置为一个0到1之间的小数,当集群中的健康实例占比小于保护阈值时,会触发保护功能。触发后,Nacos 在触发保护功能后,会根据实例的健康状态和权重,计算出一个有效权重,然后按照有效权重的比例返回实例给调用者。这样,健康的实例会有更高的概率被选中,而非健康的实例会有更低的概率被选中,阻止流量过度向少量实例集中。

  3. 临时实例/永久实例 :Nacos 中的实例分为临时实例和永久实例,临时实例的生命周期和服务的运行周期相同,服务停止运行 Nacos 中就会将临时实例删除;而永久实例即使程序终止,也会保留到 Nacos 中。可以在配置文件中使用spring.cloud.nacos.discovery.ephemeral=false设置为永久实例。

  4. 权重:用于实现负载均衡,取值范围 0 到 10000,数值越大权重越大,被分配到的概率越大。取值为 0 时表示下线。

相关推荐
后端小张1 小时前
【JAVA 进阶】Mybatis-Plus 实战使用与最佳实践
java·spring boot·spring·spring cloud·tomcat·mybatis·mybatis plus
青鱼入云13 小时前
介绍Spring Cloud Stream
spring cloud·微服务
青鱼入云13 小时前
介绍一下Ribbon的工作原理
spring cloud·微服务·ribbon
青鱼入云1 天前
Ribbon是如何与服务注册中心nacos交互的
spring cloud·微服务·ribbon
青鱼入云1 天前
OpenFeign介绍
spring cloud·微服务
勇往直前plus1 天前
学习和掌握RabbitMQ及其与springboot的整合实践(篇一)
spring boot·学习·spring cloud·rabbitmq·java-rabbitmq
杨DaB1 天前
【SpringCloud】Eureka
spring cloud·eureka·1024程序员节
洛克大航海2 天前
7-SpringCloud-服务网关 Gateway-高级特性 Route
java·spring cloud·gateway·route
我命由我123452 天前
Spring Cloud - Spring Cloud 声明式接口调用(Fiegn 声明式接口调用概述、Fiegn 使用)
java·后端·spring·spring cloud·微服务·架构·java-ee
杨DaB3 天前
【SpringCloud】Ribbon(LoadBalancer ) 和 Feign
spring·spring cloud·ribbon·feign·loadbalance