Skip to content

服务发现

配置中心管"应用读什么配置",服务发现管"一个服务名下面当前有哪些可用实例"。Nacos 同时做这两件事,部署后要分别验证配置读取和服务注册两条链路。

一、服务和实例——两个层级

服务是逻辑名称,实例是具体的可连接地址。order-service 是服务名,它下面可以有多个实例:

服务注册和查询时会反复出现这些字段:

字段说明示例
serviceName服务名order-service
groupName服务分组DEFAULT_GROUP
ip实例 IP192.168.10.13
port实例端口18080
clusterName集群名DEFAULT
healthy是否健康true
weight权重1.0
metadata附加信息version=v1zone=az1

Nacos 返回的不只是 IP:PORT——还包含健康状态、权重、元数据。客户端可以基于这些信息做负载均衡(按权重分配请求)、灰度路由(按版本标签过滤)、就近访问(按 zone 筛选)。

二、临时实例和持久实例

临时实例:普通微服务最常用的方式。客户端 SDK 注册后持续发送心跳,Nacos 超过一定时间收不到心跳就标记不健康,再超时就摘除。服务进程停了,实例从注册中心消失,调用方后续不再拿到它。

持久实例:由人通过 API 或控制台注册的一条固定记录,不依赖客户端心跳自动删除。适合少量固定后端或需要人工维护的服务条目。

bash
# 注册临时实例(默认)
curl -sS -X POST 'http://127.0.0.1:8848/nacos/v3/client/ns/instance' \
  -d 'serviceName=ops-demo-service' \
  -d 'groupName=DEFAULT_GROUP' \
  -d 'ip=192.168.10.13' \
  -d 'port=18080' \
  -d 'username=nacos' \
  -d 'password=nacos'

# 注册持久实例
curl -sS -X POST 'http://127.0.0.1:8848/nacos/v3/client/ns/instance' \
  -d 'serviceName=ops-demo-persistent' \
  -d 'groupName=DEFAULT_GROUP' \
  -d 'ip=192.168.10.13' \
  -d 'port=18080' \
  -d 'ephemeral=false' \
  -d 'username=nacos' \
  -d 'password=nacos'

查询实例列表:

bash
curl -sS \
  'http://127.0.0.1:8848/nacos/v3/client/ns/instance/list?serviceName=ops-demo-service&groupName=DEFAULT_GROUP&username=nacos&password=nacos'

返回字段关注 healthy(是否健康)、enabled(是否启用)、ephemeral(是否临时实例)、weight(权重)。

命令行手工注册临时实例适合验证 API,但它没有真实客户端维持心跳——过一会儿实例会被标记不健康然后消失。这是正常的,不代表 Nacos 有问题。业务应用由 SDK 注册,SDK 处理心跳续约和断线重连。

三、心跳——临时实例的存活依据

临时实例依赖心跳。应用定期告诉 Nacos "我还活着",Nacos 超过一段时间没收到心跳就把实例标记为不健康。常见故障场景:应用日志里反复报 Nacos 连接失败,几分钟后调用方开始找不到该服务。此时控制台服务名还在,但实例健康状态变了——"服务名存在不等于调用正常",健康实例数和客户端日志才是关键。

四、权重和元数据

权重用于简单流量分配:权重越高,被客户端选中的概率越大。常见用途:

场景操作
灰度少量流量新版本实例权重调低(比如 0.1),老版本保持 1.0
下线前摘流量权重调低到 0 或直接禁用实例
机器性能不同高配机器给更高权重

元数据是实例上的键值对,常用于版本、机房、区域等标识:

text
version=v2
zone=shanghai-a
role=gray

只能放稳定、可解释的字段。临时排查随手加的标签如果没有清理,后续做灰度或路由判断时可能变成脏条件——一个实例的元数据里同时有 version=v1role=gray,而灰度规则又是按 role 过滤,行为就和预期不一致了。

五、服务发现的排查层次

"服务发现失败"不能笼统排查,要按链路分层:

层次检查内容常见问题
应用侧客户端是否成功注册,日志里有没有连接/鉴权异常serviceName 为空、连错 Nacos 地址
Nacos 服务侧服务名、分组、命名空间是否一致namespace 不一致导致"查不到"
实例侧健康状态、IP/端口、权重心跳断了、端口没有监听
网络侧应用到 Nacos 的 8848/9848 是否通防火墙只放了 8080
消费侧调用方是否拿到最新实例列表,本地缓存是否过期客户端缓存了旧列表

出现"服务不存在"时,把调用方使用的 namespace/group/serviceName 写出来,再和控制台逐一比对。大量"服务不存在"的问题最后发现是:开发调的是 dev namespace,测试同学在 test namespace 的 Nacos 控制台查——看起来同名服务,实际上两个命名空间互不相通。