Nacos 服务注册与发现
服务注册与发现是注册中心的核心职能:应用启动时把自己的 ip:port 告诉 Nacos(注册),调用方用服务名向 Nacos 要可用实例列表(发现)。本章先讲 OpenAPI 用法,再给 Java 客户端示例。
注册服务(OpenAPI)
注册走 POST /nacos/v1/ns/instance,把服务名和实例地址作为参数提交:
curl -X POST 'http://localhost:8848/nacos/v1/ns/instance' \
-d 'serviceName=order-service&ip=192.168.1.10&port=8080&weight=1'
# 输出:ok
常用参数如下:
| 参数 | 含义 | 默认值 |
|---|---|---|
| serviceName | 服务名 | 必填 |
| ip / port | 实例地址 | 必填 |
| weight | 权重 | 1.0 |
| ephemeral | 临时/持久实例 | true(临时) |
| clusterName | 实例所在集群 | DEFAULT |
| namespaceId | 命名空间 | public |
| groupName | 分组 | DEFAULT_GROUP |
查询服务实例
发现侧用 GET /nacos/v1/ns/instance/list 拉取某服务下的实例列表,正常响应如下(节选):
curl -X GET 'http://localhost:8848/nacos/v1/ns/instance/list?serviceName=order-service'
{
"name": "DEFAULT_GROUP@@order-service",
"hosts": [
{
"ip": "192.168.1.10",
"port": 8080,
"weight": 1.0,
"healthy": true,
"enabled": true,
"ephemeral": true,
"clusterName": "DEFAULT",
"metadata": {}
}
]
}
调用方拿到 hosts 数组后,通常会过滤 healthy 为 true 的实例再做负载均衡(见第 6 章)。
心跳与健康检查
实例的健康状态由两种机制维护:
- 临时实例(默认):客户端定期发心跳保活。1.x 基于 HTTP,约定每 5 秒一次、约 15 秒收不到即判定不健康并摘除;2.x 改为 gRPC 长连接,连接断开即摘除,机制更轻
- 持久实例:由服务端主动发起健康检查,结果同样反映在 healthy 字段
健康检查的作用是"自动摘除":实例宕机后不必人工处理,Nacos 会把不健康实例从可发现列表里移除,避免调用方把请求打到死节点。
Java 客户端注册与发现
引入 com.alibaba.nacos:nacos-client 依赖后,用 NacosNamingService 即可(以下片段需放入 main 方法并处理 NacosException):
NacosNamingService naming = new NacosNamingService("localhost:8848");
// 注册实例
naming.registerInstance("order-service", "192.168.1.10", 8080);
// 查询该服务的全部实例(第二个参数 false 表示包含不健康实例)
List<Instance> all = naming.getAllInstances("order-service", false);
System.out.println(all.size()); // 输出:1
更常见的用法是主动订阅:服务列表一变(注册、注销、上下线),本地缓存立即刷新:
naming.subscribe("order-service", new EventListener() {
public void onEvent(Event event) {
System.out.println("服务列表变更:" + event);
}
});
注销服务
应用优雅停机时应主动注销,OpenAPI 与 Java 客户端用法如下:
curl -X DELETE 'http://localhost:8848/nacos/v1/ns/instance?serviceName=order-service&ip=192.168.1.10&port=8080'
# 输出:ok
应用内则调用 naming.deregisterInstance("order-service", "192.168.1.10", 8080); 注销同一实例。
小结
注册与发现就是一对操作:注册方 POST 自己的 ip:port(或 SDK 注册),发现方 GET 服务名拿到 hosts 并过滤健康实例;健康检查负责自动摘除故障节点,客户端 SDK 则把这一过程封装成几行代码并支持订阅刷新。