Nacos 的配置中心的使用我们已经了解👉使用 SpringBoot 连接 Nacos 配置中心实现配置的热更新 - 掘金 (juejin.cn) ,本篇介绍如何使用 Nacos 的注册中心。
一、Nacos 注册中心
注册中心通常有两个角色。
- 服务提供者(生产者):对外提供服务的微服务应用,将自己的服务地址注册到注册中心,以供消费者发现和调用。
- 服务调用者(消费者):调用其它微服务的应用程序,向注册中心订阅自己需要的服务,并基于服务提供者注册的信息发起远程调用。
(一)生产者实现
这里假设你已经知道如何创建多模块项目。(如何创建?👉构建强大的 Spring Boot 多模块项目:一步步指南 - 掘金 (juejin.cn))
- 将服务注册到
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>
- 创建两个子模块,分别在配置文件中(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;
}
}
- 启动 Nacos 服务、运行两个子模块,打开 Nacos 控制台http://localhost:8848/nacos/index.html。
点击"详情":
可以看到每个子模块的ip+端口信息,可以根据ip、端口来访问接口(这不是重点)。
(二)消费者实现
注册中心消费者的实现要复杂一些,消费者要调用生产者的HTTP
接口,需要引入SpringCloudOpenFeign
进行HTTP
调用(构造HTTP请求来调用生产者的接口);为了实现负载均衡,还要添加客户端负载均衡器SpringCloudLoadBalancer
。这里的消费者,就是一个模块调用其它模块的服务(接口),就好比用浏览器来调用后端接口一样。这样做是来看看模块间是如何通信的。
- 添加如下依赖到父模块的
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>
- 创建一个子模块
consumer
当作消费者
- 配置
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 #消费者需要一个固定端口
- 在启动类上添加
@EnableFeignClients
注解,用来开启OpenFeign
java
@SpringBootApplication
@EnableFeignClients //开启 OpenFeign
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
- 编写
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
一样。
- 调用
Openfeign
接口代码
java
@RestController
public class BusinessController {
@Autowired
private UserService userService;
@RequestMapping("/getnamebyid")
public String getNameById(Integer id){
return userService.getNameById(id);
}
}
此时我有两个生产者(子模块)pro_1
、pro_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_1
和pro_2
的url
是一样的,那返回的到底是哪一个值呢?我们直接全部启动,然后访问http://localhost:8080/getnamebyid?id=3
好像访问的是pro_1
难道真是这样吗?再刷新一次:
又访问了pro_2
了。因为在使用OpenFeign
进行服务间通信时,默认的负载均衡策略是轮询调用。这意味着,如果服务集群中有多个实例提供了同一个接口,OpenFeign
会依次将请求分发到每个实例上,每个实例都有平等的机会被调用。这种方式可以确保所有的服务实例都能得到均匀的负载,避免了某些实例被过度使用而其他实例空闲的情况。
(OpenFeign以及LoadBalancer负载均衡等详细的内容后续会更新,本篇只是演示注册中心的使用方法以及作用)
(三)注册中心的交互流程
看完上面一巴拉的文字可能还是有一点蒙,不过没关系,下面用图来描述整个过程。
上面的pro_1
、pro_2
就相当于服务提供者,它们都注册到了Nacos
的注册中心。接着consumer
(消费者)也把自己注册到注册中心,这时它可以拉取服务列表,看到有哪些服务提供者,从而调用该服务(通过OpenFeign
来调用)。
(四)注册中心参数说明
-
分组 :注册服务所在的组名,默认为 DEFAULT_GROUP,可以在配置文件中
spring.cloud.nacos.discovery.group=groupName
来设置。 -
保护阈值:健康节点要求的最小百分比。保护阈值应设置为一个0到1之间的小数,当集群中的健康实例占比小于保护阈值时,会触发保护功能。触发后,Nacos 在触发保护功能后,会根据实例的健康状态和权重,计算出一个有效权重,然后按照有效权重的比例返回实例给调用者。这样,健康的实例会有更高的概率被选中,而非健康的实例会有更低的概率被选中,阻止流量过度向少量实例集中。
-
临时实例/永久实例 :Nacos 中的实例分为临时实例和永久实例,临时实例的生命周期和服务的运行周期相同,服务停止运行 Nacos 中就会将临时实例删除;而永久实例即使程序终止,也会保留到 Nacos 中。可以在配置文件中使用
spring.cloud.nacos.discovery.ephemeral=false
设置为永久实例。 -
权重:用于实现负载均衡,取值范围 0 到 10000,数值越大权重越大,被分配到的概率越大。取值为 0 时表示下线。