200字
Nacos 学习笔记
2023-01-20
2023-01-20

最近项目要上微服务,Leader 让我先搞懂 Nacos。花了几天时间把 Nacos 的服务注册、配置管理、集群搭建都过了一遍,记录一下。

Nacos 是干啥的

简单说就是两个功能:
1. 服务注册发现 —— 谁上线了、谁还活着、怎么找到对方
2. 配置中心 —— 配置集中管理,改了不用重启服务

以前我们用 Eureka 做注册中心,Spring Cloud Config 做配置,两套东西要维护。Nacos 把这两个合在一起了,省事很多。

环境搭建

单机启动

去 GitHub 下个 release 包,解压直接启动就行:

wget https://github.com/alibaba/nacos/releases/download/2.2.3/nacos-server-2.2.3.tar.gz
tar -xzf nacos-server-2.2.3.tar.gz
cd nacos
sh bin/startup.sh -m standalone

启动完访问 http://localhost:8848/nacos,默认密码 nacos/nacos。

  1. 8848 HTTP

  2. 9848 gRPC(客户端连这个)

  3. 9849 gRPC(集群间通信)

  4. dev 命名空间 —— 开发环境的服务

  5. test 命名空间 —— 测试环境的

  6. prod 命名空间 —— 生产环境的

  7. 服务发现解决了「服务在哪」的问题

  8. 配置中心解决了「配置怎么统一管理」的问题

  9. 命名空间解决了「环境隔离」的问题

  10. 健康检查解决了「挂了怎么办」的问题

我在公司服务器上部署的时候只开了 8848,结果服务死活注册不上,看了半天日志才发现是 gRPC 端口没开放。这个问题卡了我快一个小时…所以 2.x 部署一定要记得防火墙把这三个端口都放行。

接 MySQL

默认用的内嵌 Derby 数据库,重启数据就没了。生产肯定要换 MySQL。

建个数据库 nacos_config,执行 conf/nacos-mysql.sql,然后改 application.properties:

spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=your_password

服务注册发现

基本接入

先加依赖:


com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery

配置 application.yml:

spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: dev

启动类加个 @EnableDiscoveryClient 就完事了。启动后在 Nacos 控制台的服务列表里就能看到了。

服务间怎么调用

我试了两种方式:

方式一:RestTemplate + @LoadBalanced

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

// 用服务名直接调用,不用写 IP
restTemplate.getForObject("http://user-service/users/1", UserDTO.class);

简单粗暴,但用起来不够优雅。

方式二:OpenFeign(推荐)

@FeignClient(name = "user-service")
public interface UserClient {
@GetMapping("/users/{id}")
UserDTO getUser(@PathVariable("id") Long id);
}

像调本地方法一样调远程服务,代码干净多了。实际项目里我们用的都是 Feign。

命名空间这个东西

一开始我没太搞懂命名空间有什么用,后来才明白就是环境隔离

  1. 8848 HTTP

  2. 9848 gRPC(客户端连这个)

  3. 9849 gRPC(集群间通信)

  4. dev 命名空间 —— 开发环境的服务

  5. test 命名空间 —— 测试环境的

  6. prod 命名空间 —— 生产环境的

  7. 服务发现解决了「服务在哪」的问题

  8. 配置中心解决了「配置怎么统一管理」的问题

  9. 命名空间解决了「环境隔离」的问题

  10. 健康检查解决了「挂了怎么办」的问题

不同命名空间的服务互相看不到。这样就不会出现开发环境的服务调到生产环境去了这种事故。

配置管理

这个功能我觉得比服务发现更实用。

怎么用

加依赖:


com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config

注意配置要写在 bootstrap.yml 里,不是 application.yml!因为 Nacos 的配置加载时机比 application.yml 早。这个我也踩过坑,写在 application.yml 里死活读不到配置。

spring:
application:
name: user-service
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
namespace: dev

然后在 Nacos 控制台创建配置文件,Data ID 格式是:user-service.yaml

动态刷新

这是我觉得 Nacos 配置中心最香的地方。在 Controller 上加 @RefreshScope:

@RestController
@RefreshScope
public class ConfigController {
@Value("${switch.new-feature:false}")
private boolean newFeature;

@GetMapping("/switch")
public boolean getSwitch() {
return newFeature;
}
}

在 Nacos 控制台改一下 switch.new-feature 的值,接口返回值立马就变了,完全不用重启服务。灰度发布、功能开关这种场景特别好用。

共享配置

项目里有很多公共配置比如 Redis、数据库连接,不可能每个服务都写一遍。Nacos 支持 shared-configs:

spring:
cloud:
nacos:
config:
shared-configs:
- data-id: common.yaml
refresh: true

这样所有服务都能引用 common.yaml 里的配置了。

健康检查

Nacos 支持两种模式:

临时实例(默认):客户端主动发心跳,5 秒一次,15 秒没心跳标记不健康,30 秒直接踢掉。适合大多数无状态服务。

持久实例:Nacos 服务端主动去探测(TCP 或 HTTP),挂了不踢掉,只是标记一下。适合那些不能随意摘除的服务。

spring:
cloud:
nacos:
discovery:
ephemeral: false # 改成持久实例

集群部署

生产至少三个节点。修改 conf/cluster.conf 写上三个 IP,前面挂个 Nginx 就行。

记得三个节点的 cluster.conf 内容要完全一样,不一样的话集群数据会出问题。

小结

学完 Nacos 之后我的理解:

  1. 8848 HTTP

  2. 9848 gRPC(客户端连这个)

  3. 9849 gRPC(集群间通信)

  4. dev 命名空间 —— 开发环境的服务

  5. test 命名空间 —— 测试环境的

  6. prod 命名空间 —— 生产环境的

  7. 服务发现解决了「服务在哪」的问题

  8. 配置中心解决了「配置怎么统一管理」的问题

  9. 命名空间解决了「环境隔离」的问题

  10. 健康检查解决了「挂了怎么办」的问题

整体上手不难,官方文档也比较全(而且是中文的这点很加分)。主要坑在 2.x 的 gRPC 端口和 bootstrap.yml 的加载顺序,注意这两个就行。

下一步打算研究 Sentinel 做限流熔断,到时候再写笔记。

评论