什么是Nacos?
Nacos 是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
-
Nacos的关键特性?
-
服务发现和服务健康监测
-
动态配置服务
-
动态 DNS 服务
-
服务及其元数据管理
-
当前推荐的稳定版本为2.1.1
Nacos注册中心
-
Nacos注册中心的工作原理
-
Nacos注册中心概念
-
服务:通过预定义接口网络访问的提供给客户端的软件功能。
-
实例:提供一个或多个服务的具有可访问的IP和Port的进程。
-
服务注册中心:存储服务实例和服务负载均衡策略的数据库。服务实例在启动的时候会将自己的服务信息注册到注册表,并且会在服务关闭时注销。服务路由器的客户端已拉取注册表的信息来发表可用的服务实例。服务注册中心可能还会调用服务实例的健康检查服务来检测该实例是否能够正常处理请求。
-
服务元数据:Nacos数据(如配置和服务)描述信息,如服务版本、权重、容灾策略、负载均衡策略、鉴权配置、各种自定义标签 (label),从作用范围来看,分为服务级别的元信息、集群的元信息及实例的元信息。
-
服务提供者:指提供可服用和可调用的服务的应用方。
-
服务消费者:是指可发起对某个服务调用的应用方。
-
-
Nacos注册中心核心功能
-
服务注册:Nacos Client会通过发送REST请求的方式向Nacos Server注册自己的服务,提供自身的元数据,比如ip、端口等信息。Nacos Server接收到注册请求后,就会把这些元数据信息存储在一个双层的内存Map中。
-
服务心跳:在服务注册后,Nacos Client会维护一个定时心跳来持续通知Nacos Server,说明服务一直处于可用状态,防止被剔除。默认5s发送一次心跳。
-
服务同步:Nacos Server集群之间会互相同步服务实例,用来保证服务信息的一致性。
-
服务发现:服务消费者(Nacos Client)在调用服务提供者的服务时,会发送一个REST请求给Nacos Server,获取上面注册的服务清单,并且缓存在Nacos Client本地,同时会在Nacos Client本地开启一个定时任务定时拉取服务端最新的注册表信息更新到本地缓存。
-
服务健康检查:Nacos Server会开启一个定时任务用来检查注册服务实例的健康情况,对于超过15s没有收到客户端心跳的实例会将它的healthy属性置为false(客户端服务发现时不会发现),如果某个实例超过30秒没有收到心跳,直接剔除该实例(被剔除的实例如果恢复发送心跳则会重新注册)。
Nacos部署
Nacos环境搭建:
-
单机模式 - 用于测试和单机试用。
-
集群模式 - 用于生产环境,确保高可用。
-
多集群模式 - 用于多数据中心场景。
-
-
引入相关依赖
properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.boot.version>2.6.11</spring.boot.version>
<spring.cloud.version>2021.0.4</spring.cloud.version>
<spring.cloud.alibaba.version>2021.0.4.0</spring.cloud.alibaba.version>
</properties>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
微服务(Nacos Client)整合Nacos注册中心(Nacos Server)
-
引入相关依赖
properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.boot.version>2.6.11</spring.boot.version>
<spring.cloud.version>2021.0.4</spring.cloud.version>
<spring.cloud.alibaba.version>2021.0.4.0</spring.cloud.alibaba.version>
</properties>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
-
配置服务提供者provider-service
-
服务提供者可以通过Nacos的注册与发现机制将服务注册到Nacos Server上。
-
引入依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
-
配置Nacos注册中心
server:
port: 8091
servlet:
context-path: /provider-context
spring:
application:
name: provider-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
-
启动provider-service看是否成功注册到Nacos中
可以看到provider-service已经注册到Nacos上了
-
配置服务消费者consumer-service 服务消费者可以通过Nacos的服务注册发现功能从Nacos Server中获取它要调取的服务。
-
引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<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>
-
配置消费者服务
server:
port: 9092
servlet:
context-path: /consumer-context
spring:
application:
name: consumer-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
-
启动consumer-service服务,看Nacos控制台界面是否有该服务注册上
-
通过RestTemplate进行服务调用
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplateLB(){
return new RestTemplate();
}
}
@Resource
private RestTemplate restTemplateLB;
@GetMapping("/testInvoke")
public String testInvoke(){
String url = "http://provider-service/provider-context/provider/test";
String forObject = restTemplateLB.getForObject(url, String.class);
System.out.println(forObject);
return forObject;
}
-
通过Feign来发起调用
@FeignClient(value = "provider-service")
public interface ConsumerService {
@GetMapping("/provider-context/provider/test")
String test();
}
@Resource
private ConsumerService consumerService;
@GetMapping("/testInvoke")
public String testInvoke(){
String url = "http://provider-service/provider-context/provider/test";
String test = consumerService.test();
return test;
}
关于Nacos的负载均衡
由上文可知,Nacos的负载策略是在服务消费方做的,通过RestTemplate + @LoadBalanced,其底层就是通过spring cloud LoadBalancer来在客户端做负载均衡的。如果是通过Feign来调用服务提供方的方法,在其底层则是通过Ribbon来实现负载均衡。(spring cloud 2021版本之后也默认用loadbalancer了)其原理都是根据服务名provider-service找到对应的路由表(ip:port)列表,然后根据负载策略选择其中的一个ip:port发起http调用。
-
负载均衡策略
如果某服务提供方有多个实例,则默认采用轮询的策略进行访问。(LoadBalancer默认的负载策略)
-
provider-service起三个不同实例,验证负载策略
-
consumer-service连续发起多次调用,可以看到服务消费端会轮询访问服务提供方的不同实例
关于权重
实例级别的配置。权重为浮点数。权重越大,分配给该实例的流量越大。范围值是1-100,默认是1。权重的配置方式有两种
-
通过application.yml配置文件配置:
spring.cloud.nacos.discovery.weight
,此种方式每次注册服务到Nacos Server的时候都会以该值设置实例的权重。 -
在Nacos控制台界面直接调整已注册服务的权重,服务重新注册后该配置会失效。
服务优雅上下线
通过Nacos的控制台界面,可以优雅地控制服务实例的上下线操作。下线后的实例将不会再被服务消费方访问。