记得去年在外省给某事业单位给科技处的领导作关于国产化微服务项目的汇报,该处长要我详细讲解一下Nacos的来龙去脉。我问他为什么要单独了解这块,他说现在国产化已经是趋势了,他其实也想深度的了解一下,这款产品是如何演化而来,希望通过了解该产品的来龙去脉深度思索一下,他所辖范围之内系统国产化的一些思路。记得当时我也是做足了工作,然后选择一个时间给他单独汇报,会后领导反响还不错,领导总结道:Nacos适应了国内企业数字化转型的需求,契合了国内企业对于构建稳定、高效微服务体系的诉求。今天我将当时的课件整理一下,在这里留下文字痕迹。也希望用这种方式和大家一起学习探讨。
2015 年,阿里巴巴内部微服务规模已达数万实例,传统服务发现组件(如 ZooKeeper)在弹性伸缩、配置管理等方面逐渐暴露出不足:
因此,阿里中间件团队开发了 Nacos(Naming and Configuration Service),作为内部微服务基础设施的核心组件。
2018 年,Nacos 正式开源并加入 Spring Cloud 生态,迅速成为国内微服务领域的主流技术:
根据 InfoQ 2023 年微服务技术调研:
为了便于理解,我们可以Nacos 的整体架构可以类比为一个城市的交通管理系统:代码部分我以python语言进行注解
+----------------+ +----------------+ +----------------+
| 服务提供者 | | Nacos服务器集群 | | 服务消费者 |
| (如餐厅) | | (交通指挥中心) | | (如食客) |
+----------------+ +----------------+ +----------------+
| ^ ^
| (注册服务: 我这里有川菜) | |
v | |
+----------------+ +----------------+ +----------------+
| 服务注册中心 |<--->| 配置中心 |<--->| 服务发现客户端 |
| (餐厅注册表) | | (交通规则库) | | (食客导航App) |
+----------------+ +----------------+ +----------------+
| | |
| (服务变更通知) | (配置变更推送) |
v v v
+----------------+ +----------------+ +----------------+
| 健康检查模块 | | 事件总线 | | 本地缓存 |
| (巡查员) | | (广播系统) | | (本地餐厅列表) |
+----------------+ +----------------+ +----------------+
当一个服务提供者启动时,它会向 Nacos 服务器发送注册请求,就像一家新餐厅需要在美食地图上登记信息:
# Python代码示例:服务注册
from nacos import NacosClient
nc = NacosClient("127.0.0.1:8848")
nc.add_naming_instance(
service_name="order-service",
ip="192.168.1.100",
port=8080,
weight=1.0,
metadata={"version": "2.0.0"}
)
Nacos 服务器将服务信息存储在内存和磁盘中:
服务消费者订阅服务时,Nacos 提供两种模式:
类似食客在餐厅门口等待叫号:
类似食客定期查看手机上的美食地图更新:
Nacos 提供多种健康检查方式:
当发现服务不健康时,Nacos 会:
Nacos 的配置管理就像餐厅修改营业时间并通知老顾客:
# Python代码示例:配置订阅
def config_changed_callback(args):
print(f"配置变更: {args}")
nc.add_config_watcher(
data_id="order-service.yaml",
group="DEFAULT_GROUP",
callback=config_changed_callback
)
当订单服务出现高并发时,Nacos 可以:
这些治理规则可以通过控制台动态配置,无需修改代码。
Nacos 支持两种一致性协议:
模式 | 适用场景 | 实现方式 | 特点 |
---|---|---|---|
AP | 电商、社交等对可用性要求高的场景 | 异步复制 | 服务注册更快,但可能读到旧数据 |
CP | 金融、支付等对一致性要求高的场景 | Raft 协议 | 数据强一致,但写入性能较低 |
可以通过一个配置文件轻松切换模式:
# 在conf/application.properties中配置
spring.profiles.active=ap
# 或
spring.profiles.active=cp
光说不练可不行,下面以python实操来实现Nacos服务的方式
首先安装 SDK:
pip install nacos-sdk-python
我们来实现一个完整的订阅示例:
from nacos import NacosClient
# 初始化客户端
nc = NacosClient(
server_addresses="127.0.0.1:8848", # Nacos服务器地址
namespace="public", # 命名空间ID
username="nacos", # 用户名
password="nacos" # 密码
)
# 定义服务变更回调函数
def service_changed_callback(services):
print(f"服务列表变更: {services}")
# 这里可以实现服务列表变更后的处理逻辑
# 例如更新本地缓存、通知负载均衡器等
# 订阅服务
nc.subscribe(
service_name="user-service", # 服务名
group_name="DEFAULT_GROUP", # 组名
cluster_name="DEFAULT", # 集群名
callback=service_changed_callback # 回调函数
)
# 获取当前服务列表
instances = nc.list_naming_instance(
service_name="user-service",
group_name="DEFAULT_GROUP",
cluster_name="DEFAULT"
)
print(f"当前服务实例: {instances}")
# 保持主线程运行,使订阅持续生效
try:
import time
while True:
time.sleep(1)
except KeyboardInterrupt:
print("程序退出")
方法 | 功能 | 参数说明 |
---|---|---|
NacosClient() |
初始化客户端 | server_addresses : Nacos 服务器地址namespace : 命名空间username/password : 认证信息 |
subscribe() |
订阅服务 | service_name : 服务名group_name : 组名callback : 服务变更回调函数 |
list_naming_instance() |
获取服务实例列表 | service_name : 服务名group_name : 组名clusters : 集群名列表 |
unsubscribe() |
取消订阅 | service_name : 服务名group_name : 组名 |
当调用subscribe()
方法时,SDK 内部执行以下操作:
再讲一下服务订阅底层的实现机制,总结一下主要在三个方面
Nacos 的推模式实际上是长轮询机制:
这种机制相比传统轮询有以下优势:
Nacos 在 AP 模式下,服务注册与订阅采用最终一致性:
在 CP 模式下,服务注册与订阅采用强一致性:
看看实践中代码如何实现吧
建议配置服务的健康检查:
# 注册服务时配置健康检查
nc.add_naming_instance(
service_name="order-service",
ip="192.168.1.102",
port=8080,
weight=1.0,
cluster_name="DEFAULT",
ephemeral=True, # 临时实例,需要定时发送心跳
metadata={"version": "2.0.0"},
# 配置健康检查
healthy_check_interval=5, # 健康检查间隔(秒)
healthy_check_timeout=10, # 健康检查超时时间(秒)
max_healthy_check_tries=3 # 最大健康检查失败次数
)
为提高性能,建议实现多级缓存:
import threading
import time
from cachetools import TTLCache
# 本地缓存,保存最近300秒的服务信息,最多100个条目
service_cache = TTLCache(maxsize=100, ttl=300)
cache_lock = threading.Lock()
def get_service_instances(service_name):
# 优先从本地缓存获取
with cache_lock:
if service_name in service_cache:
return service_cache[service_name]
# 缓存未命中,从Nacos获取
instances = nc.list_naming_instance(service_name)
# 更新缓存
with cache_lock:
service_cache[service_name] = instances
return instances
import requests
from tenacity import retry, stop_after_attempt, wait_fixed
@retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
def safe_subscribe(service_name):
try:
nc.subscribe(
service_name=service_name,
cb=message_handler
)
except requests.exceptions.RequestException as e:
print(f"订阅失败: {e}, 正在重试...")
raise # 触发重试
问题 | 原因 | 解决方案 |
---|---|---|
订阅不生效 | 命名空间、组名不匹配 | 检查命名空间 ID、组名是否正确 |
服务变更不通知 | 长轮询连接断开 | 实现断线重连机制,添加心跳检测 |
获取不到服务实例 | 服务未注册或已下线 | 检查服务提供者是否正常运行,查看 Nacos 控制台 |
订阅延迟高 | 网络问题或 Nacos 负载过高 | 检查网络状况,增加 Nacos 集群节点 |
建议采用至少 3 节点的集群部署模式:
+----------------+ +----------------+ +----------------+
| Nacos Node 1 | | Nacos Node 2 | | Nacos Node 3 |
| 192.168.1.10 |<--->| 192.168.1.11 |<--->| 192.168.1.12 |
+----------------+ +----------------+ +----------------+
^ ^ ^
| | |
+----------------+ +----------------+ +----------------+
| 服务提供者 | | 服务消费者 | | 配置中心客户端 |
| 应用集群 | | 应用集群 | | 应用集群 |
+----------------+ +----------------+ +----------------+
建议监控以下指标:
Nacos 确实是具有中国 “血统” 的开源产品,由阿里巴巴开发并开源 。它脱胎于阿里内部从 2008 年就开始发展的 ConfigServer,在 2018 年 7 月发布首个开源版本 V0.1.0,历经版本迭代,不断完善功能并提升性能。逐步发展成为一个成熟且被广泛应用的开源项目,展示了中国企业在分布式系统、微服务架构等关键技术领域具备强大的自主研发与创新能力。它并非对国外同类产品的模仿,而是基于自身大规模业务场景的实践经验,针对性地解决微服务治理过程中的痛点问题,如服务雪崩、配置管理混乱、服务发现延迟高等,创造出了符合本土乃至全球开发者需求的服务发现与配置管理平台。
在Nacos 在发展过程中,也是不断适配国产的操作系统、数据库等基础软件。所以目前Nacos 的服务订阅机制是微服务架构中不可或缺的一环,掌握 Nacos 服务订阅技术,能够帮助开发者构建更加弹性、高效的微服务系统,实现服务间的智能调用与治理。我也是通过 Python SDK 从基础概念入手,深入剖析了 Nacos 服务订阅的核心机制、Python 实现方式以及生产环境的最佳实践。总而言之,Nacos 作为优秀的开源解决方案,值得开发者深入学习与应用。