分布式系统设计实战 - 服务注册中心最佳选型
1、概述
前面我们学习了如何使用 SpringCloud 快速的构建一套分布式系统,通过代码案例的方式演示了 SpringBoot 、 Nacos、Gateway、Loadbalancer 以及 OpenFeign 等基本组件的使用,我们以及具备搭建一个基本的分布式系统的能力了,但是站在系统架构的层面上,我们还需要考虑很多的因素,比如注册中心的选型、服务网关选型、RPC重试机制、以及负载均衡等等。
想了很久,我们就先对服务注册中心展开深入的讨论,如何根据自己的业务系统做出合适的技术选型,后续我们再逐步的进行其他的基础设施建 展开分析。
2、服务注册中心
2.1、注册中心简介
在前面的文章 玩转 SpringCloud - 快速构建分布式系统详解 中已经介绍了 nacos 这款注册中心产品,相信你肯定知道服务注册中心是什么以及它的作用了。今天我们就来学习一下市面上主流的开源注册中心产品。主要包括 Zookeeper、Nacos、Consoul、etcd 以及过时的Eureak。
2.2、环境准备
这里我们沿用上一篇文章的中的代码案例,相关代码我已经提交到 gitee了,如果想从头开始搭建可以参考前面的文章
文章连接:
https://blog.csdn.net/qq_38701478/article/details/145702897?spm=1001.2014.3001.5501代码链接:
https://gitee.com/skr_coder/cloud-practice
软件版本信息如下:
JDK: 17
SpringBoot: 3.3.4
SpringCloud: 2023.0.3
SpringCloudAlibaba: 2023.0.3.2
2.3、Zookeeper 集成案例
2.3.1、Zookeeper 环境搭建
我们准备好 Zookeeper 的软件包,解压后来到 bin 目录 双击 zkServer.cmd 启动 Zookeeper 服务。
2.3.2、项目环境搭建
接着我们在原来的工程添加依赖信息,相关依赖信息如下
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
需要注意的是 gateway 和 Center 工程都需要添加
接着分别修改 用户服务和账户服务以及网关工程的 配置文件 ,相关内容如下:
server:port: 9000spring:application:name: account-service
# cloud:
# nacos:
# server-addr: 127.0.0.1:8848cloud:zookeeper:connect-string: 127.0.0.1:2181 # Zookeeper 服务器地址,默认端口是 2181discovery:enabled: true # 启用服务发现功能
最后分别检查启动类上是否添加了 开启服务发现的注解 @EnableDiscoveryClient
2.3.3、服务测试
上述步骤完成后即可启动三个工程进行测试了。启动后如下所示
接着我们使用工具调用 创建账户接口来 创建一个账户 相关结果如下图所示
2.3.4、 查看服务信息
我么可以使用命令行工具登陆到Zookeeper 服务端 查看相应的服务信息,双击 zkCli.cmd 打开终端,输入 ls /services 命令就可以看到 服务列表了。
我们还可以使用get 命令获取具体服务信息 ,我们先来看网关工程的服务信息
具体内容如下,相信你肯定能看懂 ,这里说明下 由于我的 网关工程没有配置应用的名字 所以 name 使用了默认值 application
{"name": "application","id": "245dada4-4057-428a-b71e-2aac9eeb36a9","address": "XY-YK-YX-WCAN","port": 80,"sslPort": null,"payload": {"@class": "org.springframework.cloud.zookeeper.discovery.ZookeeperInstance","id": "application","name": "application","metadata": {"instance_status": "UP"}},"registrationTimeUTC": 1747832116612,"serviceType": "DYNAMIC","uriSpec": {"parts": [{"value": "scheme","variable": true}, {"value": "://","variable": false}, {"value": "address","variable": true}, {"value": ":","variable": false}, {"value": "port","variable": true}]}
}
我们继续看用户服务 的信息
格式化后如下所示
{"name": "user-service","id": "bc92841d-670a-4dba-b23f-83f382950ac5","address": "XY-YK-YX-WCAN","port": 8001,"sslPort": null,"payload": {"@class": "org.springframework.cloud.zookeeper.discovery.ZookeeperInstance","id": "user-service","name": "user-service","metadata": {"instance_status": "UP"}},"registrationTimeUTC": 1747832120483,"serviceType": "DYNAMIC","uriSpec": {"parts": [{"value": "scheme","variable": true}, {"value": "://","variable": false}, {"value": "address","variable": true}, {"value": ":","variable": false}, {"value": "port","variable": true}]}
}
2.4、Consul 集成案例
2.4.1、Consul 环境准备
首先下载安装包,下载地址如下
https://developer.hashicxiazaorp.com/consul/install#windows
接着我们解压下载的软件包,cmd 进入 解压目录
参照官方文档,我们可以使用 consul agent -dev 命令启动 服务
https://developer.hashicorp.com/consul/commands
服务启动后浏览器访问 http://localhost:8500 即可进入控制台
2.4.2、项目环境准备
依赖信息如下:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-consul-discovery</artifactId></dependency>
配置信息如下:
#------ consulcloud:consul:host: 127.0.0.1 # Consul 服务地址port: 8500 # Consul 默认端口discovery:enabled: true # 启用服务发现discovery:enabled: true # 启用服务注册与发现
需要将之前的 zookeeper 和 nacos 的配置注释 或者删除
2.3.4、查看服务信息
和前面一样我们启动几个服务即可,这里我的网关工程报错了,报错信息如下:
Caused by: java.lang.IllegalArgumentException:
Consul service ids must not be empty, must start with a letter,
end with a letter or digit, and have as interior characters only letters, digits, and hyphen: 80
报错原因就是 没有设置 application name ,我们在 application.yml 中添加配置即可
spring:application:name: gateway
项目启动后,进入管理控制台查看服务信息
好家伙,我们发现服务前面都有个红叉,一看就知道 这是不好的现象。我们点进去发现报错信息如下
HTTP GET http://XY-YK-YX-WCAN:9001/actuator/health: 404 Output:
<html><body><h1>Whitelabel Error Page</h1><p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p><div id='created'>
Wed May 21 22:26:17 CST 2025</div><div>There was an unexpected error(type=Not Found, status=404).</div></body></html>
意思就是没有找到健康检查的端点,好吧 这里我们需要在 网关工程 和 Center 中 加入 actuator 依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
重启服务发现都正常了。
2.3.4、服务测试
我们打开工具测试,发现服务调用也是正常的
2.5、Eureka 介绍
曾经 Eureka 也是一种比较热门的注册中心产品,也是 第一代 SpringCloud 体系中默认的注册中心,它不需要安装单独的软件包,直接以jar包的形式与业务系统集成,可以方便、快速的实现服务注册、注销、健康检查等功能。
但是后来开源的版本停止维护了,所以大家就寻找了其他的替代方案,这里就不再提供集成的案例代码了。
2.6、Nacos 集成案例
2.6.1、Nacos 环境准备
首先我们到官方网站下载软件包 链接
https://nacos.io/?spm=5238cd80.3a4808a9.0.0.1b44411drCbw9x
我们选择下载 2.4.3 的版本,
下载完成后解压压缩包,进入bin 目录 使用 startup.cmd -m standalone 命令启动
浏览器访问 http://192.168.241.1:8848/nacos/index.html
2.6.2、项目环境准备
步骤和前面的类似,网关工程和 Center 添加 nacos 依赖,用户服务、账户服务 和 网关 修改配置文件,这里不再赘述了。
依赖信息如下 :
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
配置信息如下:
#------ nacoscloud:nacos:server-addr: 127.0.0.1:8848
修改完成后启动服务就可以在控制台看到具体的服务信息了。
2.6.3、服务测试
和前面一样的测试即可,这里不再赘述了。
2.7、Etcd 集成案例
2.7.1、Etcd 环境准备
首先下载安装包,我们这里去 github 下载。本文以 Linux 环境为例,(害。。。。Windows 下操作好几遍失败了)
https://github.com/etcd-io/etcd/releases
我么登陆到终端上,尽量使用 root 用户 或者具备 root 权限的用户
首先安装 wget 和 systemd
yum install -y wget systemd
接着创建一个 shell 脚本,脚本内容如下
# 新建一个 shell 文件vim etcd_install.sh## shell 文件中的内容ETCD_VERSION=v3.5.0
wget https://github.com/etcd-io/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz
tar xzvf etcd-${ETCD_VERSION}-linux-amd64.tar.gz
sudo mv etcd-${ETCD_VERSION}-linux-amd64/etcd /usr/local/bin/
sudo mv etcd-${ETCD_VERSION}-linux-amd64/etcdctl /usr/local/bin/
保存后给 etcd_install.sh 赋权
chmod 755 etcd_install.sh
然后运行脚本,等待执行完成即可
查看安装版本信息
安装完成后我们需要做相关的配置。
新建一个 etcd.env 文件,用于设置 Etcd 的启动参数 。
# 新建文件
vim /etc/etcd.env# 添加以下内容
# 单节点配置示例
ETCD_NAME=default
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.200.19:2379"
其中 ETCD_LISTEN_CLIENT_URLS 表示 指定 etcd 节点监听客户端连接的地址和端口,这里我们设置的 0.0.0.0 表示监听所有网络,也就是说局域网内的任意ip都能注册进来。ETCD_ADVERTISE_CLIENT_URLS 用来指定微服务访问的ip 和端口
接着 创建一个 Systemd 服务文件,用来管理 etcd 服务 ,相关命令如下
# 新建文件
vim /etc/systemd/system/etcd.service# 加入以下内容 [Unit]
Description=Etcd Server
After=network.target[Service]
Type=simple
EnvironmentFile=-/etc/etcd.env
ExecStart=/usr/local/bin/etcd
Restart=on-failure[Install]
WantedBy=multi-user.target
最后我们可以启动服务了
# 启动服务
sudo systemctl start etcd
# 查看状态
sudo systemctl enable etcd
2.7.2、项目环境准备
依赖信息
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-etcd</artifactId>
</dependency>
添加依赖
cloud:etcd:endpoints: http://192.168.200.98:2379 # Etcd 服务的地址acl: false # 是否启用访问控制列表(根据需要设置)enabled: true # 启用 Etcd 注册中心ttl: 30 # 服务注册的超时时间(可选)
最后启动项目即可进行测试。
3、CAP 理论
3.1、理论概述
前面介绍了主流的几种注册中心的集成方式 和基本的使用,这个章节里我们来聊聊 CAP 理论。CAP 理论是由计算机科学家 Eric Brewer 在 2000 年的 ACM Symposium 上提出的。旨在描述分布式计算系统中一致性、可用性和分区容忍性之间的权衡关系。
他指出在分布式系统中,无法同时满足一致性(Consistency)、可用性(Availability)和分区容忍性(Partition Tolerance)这三个要素,最多只能满足其中两个。
通常情况下,我们认为网络分区是必然存在的,因此大多数时候 P 是必选的,我们都是在 C 和 A 之间做取舍。 也就是 CP 和 AP 。
3.2、CP 系统
所谓的CP 系统 就是 牺牲可用性,保证强一致性和分区容忍性。他的典型场景有: 银行转账、库存扣减等对数据准确性要求极高的场景。
代表性的技术是 Zookeeper、Etcd、Consul(CP 模式)。当发生网络分区时,系统可能拒绝请求(如返回超时错误),直到分区恢复
3.3、AP 系统
牺牲一致性 保证高可用性和分区容忍性,但数据可能短暂不一致。
典型场景:社交媒体、电商商品详情页等容忍短暂数据延迟的场景。
代表技术:Eureka、Cassandra、Nacos(AP 模式)。
代价:用户可能读到旧数据(最终一致性)。
3.4、CA 系统
不支持网络分区,想想有哪些场景下是不存在网络分区的问题或者说是 网络是绝对可靠的 ,大概只有单机环境吧 ,很显然分布式系统中必然存在网络分区的问题。
4、BASE 理论
4.1、相关概念
下面先看看 BASE 是什么
-
BA(Basically Available)基本可用:系统在故障时仍能提供核心功能(如降级、限流)。
-
S(Soft State)软状态:允许系统中的数据存在中间状态(不同节点的数据可能暂时不一致)。
-
E(Eventual Consistency)最终一致性:经过一段时间后,所有节点的数据会达成一致。
你的注意力应该放在 E 上,也就是最终一致性。我们可以认为 BASE 是对 CAP 中 AP 架构的补充,强调通过牺牲强一致性来换取高可用性,适用于对延迟敏感但允许最终一致性的场景。
4.2、应用场景
我们在更新缓存的时候,缓存节点间数据可能短暂不一致,但最终通过异步同步达成一致。这就是 最终一致性。
4.3、CAP 和 BASE
特性 | CAP | BASE |
---|---|---|
核心目标 | 强一致性 vs 高可用性 | 高可用性 + 最终一致性 |
一致性模型 | 强一致性(CP)或弱一致性(AP) | 最终一致性 |
适用场景 | 金融交易、配置管理 | 社交网络、实时性要求低的业务 |
典型技术 | Zookeeper、Etcd | Cassandra、DynamoDB、Nacos |
5、主流注册中心比对
5.1、 Zookeeper(CP 型)
-
特点:
-
基于 ZAB 协议,强一致性(CP),牺牲可用性。
-
通过临时节点(Ephemeral Nodes)实现服务注册与心跳检测。
-
适用场景:数据一致性要求高的场景(如分布式锁、配置管理)。
-
-
缺点:
-
选举期间(30-120秒)服务不可用,不适合高可用性要求的服务发现。
-
客户端需自行处理服务列表的监听与刷新,复杂度较高。
-
5.2、Eureka(AP 型)
-
特点:
-
去中心化架构(Peer-to-Peer),强调高可用性(AP)。
-
支持自我保护机制(网络分区时保留旧数据),适合云环境。
-
与 Spring Cloud 集成度高,适合快速开发。
-
-
缺点:
-
数据最终一致性,可能出现短暂不一致。
-
默认配置下服务发现延迟较高(分钟级),需手动优化参数5。
-
5.3、Consul(CP 型)
-
特点:
-
基于 Raft 协议,强一致性(CP),支持多数据中心。
-
一站式服务(服务发现、健康检查、KV 存储、DNS 支持)。
-
适合需要跨区域部署和强一致性的场景。
-
-
缺点:
-
注册时间较长(需半数节点确认)。
-
对 Go 语言依赖较强,侵入性较高。
-
5.4、Nacos(AP/CP 可选)
-
特点:
-
支持 AP 和 CP 模式切换,灵活性高。
-
集成服务发现与动态配置管理,适合微服务全生命周期管理。
-
对 Spring Cloud 和 Dubbo 生态兼容性好,适合混合云场景。
-
-
缺点:
-
社区生态相对年轻,大规模生产验证案例较少。
-
5.5、ETCD(CP 型)
-
特点:
-
基于 Raft 协议,强一致性,性能高(每秒千级写操作)。
-
与 Kubernetes 深度集成,是云原生场景的默认选择。
-
支持 SSL 认证,安全性强。
-
-
缺点:
-
功能单一(主要面向键值存储),需额外组件支持服务发现。
-
6、 选型建议
6.1、何时选择 CP 系统
-
强一致性需求:如支付系统、分布式锁、配置中心。
-
技术栈依赖:Kubernetes(依赖 Etcd)、Dubbo(依赖 Zookeeper)。
6.2、 何时选择 AP + BASE
-
高并发高可用场景:如电商大促、社交网络热点事件。
-
容忍数据延迟:如商品评论、用户行为日志。
6.3、 混合架构实践
-
分级一致性:核心交易链路用 CP(如订单支付),非核心链路用 AP(如用户积分)。
-
Nacos 的双模式:根据服务类型切换 AP/CP 模式(如配置中心用 CP,服务发现用 AP)。
6.4、多维度选型
6.4.1、 根据 CAP 需求选择:
-
强一致性(CP)场景:
-
Zookeeper:适合传统分布式系统(如 Hadoop、Dubbo)的协调服务。
-
Consul:需多数据中心支持或一站式解决方案时优先考虑。
-
ETCD:Kubernetes 生态首选,云原生场景必选。
-
-
高可用性(AP)场景:
-
Eureka:Spring Cloud 技术栈的简单选择,适合中小规模。
-
Nacos:需要动态配置管理或混合部署时优选。
-
6.4.2、 根据技术栈选择:
-
Spring Cloud:优先 Nacos 或 Eureka(历史项目)。
-
Dubbo:推荐 Zookeeper 或 Nacos。
-
Kubernetes:ETCD 是默认选择,Consul 可作补充。
6.4.3、根据功能需求选择:
-
动态配置管理:Nacos(内置配置中心)或 Consul(需结合 Vault)。
-
多数据中心:Consul 或 Nacos(需手动配置)。
-
轻量级与易用性:Nacos(界面友好) > Eureka > Consul。
6.4.4、性能与规模:
-
大规模服务实例(万级节点):Nacos(水平扩展能力强)或 ETCD(高性能)。
-
中小规模:Eureka(简单)或 Consul(功能全面)。
7、总结
我们透彻的将 CAP 理论其实是设计上的一种理论,它主要帮助我们理解分布式系统的本质矛盾,明确架构的取舍方向。而BASE 理论则是一种实践指导,在 AP 架构下,通过最终一致性平衡业务需求与技术复杂度。有了这些基础知识的支撑 我们就可以根据自己的业务系统做出合适的 技术选型了。