nacos-注册/配置中心

基础入门

官网:nacos 官网 | 快速开始
下载:nacos 官网 | 下载服务
启动:在bin目录启动cmd,输入startup.cmd -m standalone启动nacos的服务端,访问:http://localhost:8848/nacos,就可以看到nacos的ui界面了,nacos server 账号密码都是nacos。

注册中心

将微服务注册到nacos中进行统一管理,首先微服务要引入nacos依赖:

1
2
3
4
5
6
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>

然后服务在自己的properties或yml文件中配置:

1
2
3
4
# properties
server.port=8000
spring.application.name=service-order # 服务名字
spring.cloud.nacos.server-addr=127.0.0.1:8848 # nacos地址

启动服务,在nacos的服务列表里面就可以看到这个服务了。

服务发现

服务间的远程调用通过nacos发现对方的服务,然后进行调用,后续不用手动调,这里只要加上注解,两个API作为了解。
启动类加注解@EnableDiscoveryClient,然后在需要使用的地方注入,就能发现在nacos中注册的服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Autowired
NacosDiscoveryClient nacosDiscoveryClient;
public void nacosDiscoveryClientTest(){
List<String> services = nacosDiscoveryClient.getServices();
for (String service : services) {
System.out.println("service = " + service);
List<ServiceInstance> instances = nacosDiscoveryClient.getInstances(service);
for (ServiceInstance instance : instances) {
System.out.println("instance.getHost() = " + instance.getHost());
System.out.println("instance.getPort() = " + instance.getPort());
}
}
}

远程调用服务中接口,可以在消费者的这一方配置:

1
2
3
4
5
6
7
8
@Configuration
public class ConsumerConfig {
@Bean
public RestTemplate restTemplate() {
//RestTemplate 是 Spring 框架提供的同步 HTTP 客户端模板类,它的核心作用是简化客户端与 RESTful 服务之间的 HTTP 通信。
return new RestTemplate();
}
}

之后,就可以开始调用生产者的接口了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Autowired
NacosDiscoveryClient nacosDiscoveryClient;
@Autowired
RestTemplate restTemplate;

//远程调用获取生产者信息
public Product getProductFromRemote(Long productId) {
//1、获取到生产者服务所在的所有机器IP+port
List<ServiceInstance> instances = nacosDiscoveryClient.getInstances("service-product");
ServiceInstance instance = instances.get(0);
//远程URL
String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/productId/" + productId;
log.info("远程请求:{}", url);
//2、给远程发送请求
Product product = restTemplate.getForObject(url, Product.class);
return product;
}

注册中心宕机了,还能调用吗?
可以调用,因为缓存中有地址。但如果对方服务宕机则也调不通。
原理
第一次远程调用要经过两个步骤:1.拿到nacos服务地址列表 2.给对方服务的某个地址发送请求。
第二次及后续:就会将步骤1省略,已经将地址列表放到缓存中了,即使nacos宕机也能远程调用,并且能负载均衡。

负载均衡

这个功能只能负载均衡注册到nacos的服务。首先,先引入依赖

1
2
3
4
5
<!--负载均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

然后进行测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@SpringBootTest
public class OrderApplicationTest {
@Autowired
LoadBalancerClient loadBalancerClient;

@Test
public void test() {
// 这里可以看到在启动多个生产者之后,回依次轮询调用
for (int i = 0; i < 9; i++) {
// 将nacosDiscoveryClient换为loadBalancerClient
ServiceInstance choose = loadBalancerClient.choose("service-product");
System.out.println("choose.getHost()+choose.getPort() = " + choose.getHost() + ":" + choose.getPort());
}
}
}

此外,负载均衡也可以用注解,在配置类RestTemplate()的@Bean这里加上@LoadBalanced,就可以更简单的调用:

1
2
3
4
5
6
public Product getProductFromRemoteWithLoadBalanceAnnotation(Long productId) {
//给远程发送请求;;service-product会被动态替换
String url = "http://service-product/productId/" + productId;
Product product = restTemplate.getForObject(url, Product.class);
return product;
}

配置中心

导入依赖:

1
2
3
4
5
<!--配置中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

配置文件application.properties:

1
2
3
spring.config.import=nacos:service-order.properties
#暂未用到配置中心功能,需要关闭配置检查
spring.cloud.nacos.config.import-check.enabled=false

导入了配置中心的依赖,但是没设置(用到)配置中心就会报错,解决办法,关闭自动检查

指定完配置中心后,就需要在nacos的配置列表中新建配置,保存发布之后,就和在properties中配置的一样。

Nacos中的数据集 和 application.properties 有相同的 配置项,哪个生效?
以配置中心为准,不然要配置中心干什么

自动刷新

  1. @Value(“${xx}”) 获取配置 + @RefreshScope 实现自动刷新,但是会产生一个问题:nacos配置中修改后,不重启服务,发请求不能自动更新修改后的数据。

    实时更新配置显示的办法:在@RestController上加@RefreshScope即可

  2. @ConfigurationProperties 无感自动刷新,@ConfigurationProperties(value = “order”),配置批量绑定在nacos下,可以无需@RefreshScope就能实现自动刷新

    还是要在配置类加上@RefreshScope,配置变更会触发Bean的重建,从而加载最新的配置值

数据隔离

配置中心基于项目激活哪个环境标识,动态指定名称空间,动态加载指定文件和配置。

Maven Profiles实现
  1. 父 POM 添加 Profiles
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<profiles>
<profile>
<id>dev</id>
<properties>
<spring.profile>dev</spring.profile>
<nacos.server.address>127.0.0.1:8848</nacos.server.address>
</properties>
<activation>
<!-- 是否默认生效 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!-- 按需添加 test / prod -->
</profiles>
  1. 父 POM 开启资源过滤
1
2
3
4
5
6
7
8
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
  1. 子模块创建 bootstrap.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
spring:
application:
name: 你的服务名
profiles:
active: @spring.profile@ # 这个占位符对应pom中的spring.profile
cloud:
nacos:
discovery:
server-addr: @nacos.server.address@ # 对应pom中的nacos.server.address
config:
server-addr: @nacos.server.address@
file-extension: yml
shared-configs:
# 测试环境拼接出来就是 application-dev.yml
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
  1. Nacos 中创建对应配置文件

    • 打开 Nacos 管理界面
    • 新建配置,Data ID 格式为 {服务名}-{环境}.yml
    • 填入对应环境的数据库连接、Redis 地址等配置
  2. 激活profile

    场景 命令
    指定使用 prod 环境 mvn clean package -P prod
    使用默认环境 直接 mvn clean package
    外部传入动态参数 mvn clean package -Dmy.param=value
  3. 验证

1
2
3
4
5
6
7
8
9
# 默认 dev 环境打包
mvn clean package

# 指定 test 环境打包
mvn clean package -P test

# 解压 jar 包查看 bootstrap.yml 是否替换成功
jar xf target/xxx.jar BOOT-INF/classes/bootstrap.yml
cat BOOT-INF/classes/bootstrap.yml

参考

https://blog.csdn.net/weixin_56884174/article/details/145573890