摘要:一般都提供服务注册与发现、客户端负载均衡、配置管理功能。。
目录
[TOC]
服务注册与发现
目的:一般都提供服务注册与发现、客户端负载均衡、配置管理功能。
服务注册与发现机制:
- 每个微服务都会向注册中心去注册(自己的地址及端口信息),注册中心维护着服务名称与服务实例的对应关系。
- 每个微服务都会定时从注册中心获取服务列表,同时汇报自己的运行情况。
- 当有的服务需要调用其他服务时,就可以从自己获取到的服务列表中获取实例地址进行调用。
- 如,用户服务调用订单服务的多个实例。
通常有几种解决办法:
-
服务地址硬编码:写死在数据库或者配置文件,如,通过DNS域名解析进行路由寻址。
-
服务动态注册与发现:用于微服务间相互调用。

基本原理
服务注册
有两种形式:客户端注册和代理注册。
- 客户端注册:服务自己负责注册与注销的工作。当服务启动后注册线程向注册中心注册,当服务下线时注销自己。
- 缺点:注册注销逻辑与服务的业务逻辑耦合在一起,如果服务使用不同语言开发,需要适配多套服务注册逻辑。
- 代理注册:由一个单独的代理服务负责注册与注销。当服务提供者启动后以某种方式通知代理服务,然后代理服务负责向注册中心发起注册工作。比如?
- 缺点:多引用了一个代理服务,并且代理服务要保持高可用状态。


服务发现
分为客户端发现和代理发现。
- 客户端发现:客户端负责向注册中心查询可用服务地址,获取到所有的可用实例地址列表后,客户端根据负载均衡算法选择一个实例发起请求调用。
- 这种方式非常直接,客户端可以控制负载均衡算法。
- 缺点:获取实例地址、负载均衡等逻辑与服务的业务逻辑耦合在一起,如果服务发现或者负载平衡有变化,那么所有的服务都要修改重新上线。
- 代理发现:新增一个路由服务负责服务发现获取可用的实例列表。服务消费者如果需要调用服务A的一个实例,可以直接将请求发往路由服务,路由服务根据配置好的负载均衡算法,从可用的实例列表中选择一个实例将请求转发过去即可。
- 如果发现实例不可用,路由服务还可以自行重试,服务消费者完全不用感知。


心跳机制
摘机(注销):如果服务有多个实例,其中一个实例出现宕机,注册中心是可以实时感知到,并且将该实例信息从列表中移出。
如何实现摘机?业界比较常用的方式是通过心跳检测的方式实现,有主动和被动两种方式。
- (注册中心)被动心跳检测:服务主动向注册中心发送心跳消息。时间间隔可自定义,比如配置5秒发送一次,注册中心如果在三个周期内(比如说15秒)没有收到实例的心跳消息,就会将该实例从列表中移除。如,服务A的实例2。
- 主动心跳检测:注册中心主动发起,每隔几秒中会给所有列表中的服务实例发送心跳检测消息,如果多个周期内未发送成功或未收到回复就会主动移除该实例。


注册中心原理
在使用注册中心时,一共有三种角色:
- 服务提供者(
Service Provider、Server):- 启动时,向 Registry 注册自己为一个服务(Service)的实例(Instance)。
- 同时,定期向 Registry 发送心跳,告诉自己还存活。
- 关闭时,向 Registry 取消注册。
- 服务消费者(
Service Consumer、Client):- 启动时,向 Registry 订阅使用到的服务,并缓存服务的实例列表在内存中。
- 后续,Consumer 向对应服务的 Provider 发起调用时,从内存中的该服务的实例列表选择一个,进行远程调用。
- 关闭时,向 Registry 取消订阅。
- 注册中心(
Registry):- Provider 超过一定时间未心跳时,从服务的实例列表移除。
- 服务的实例列表发生变化(新增或者移除)时,通知订阅该服务的 Consumer,从而让 Consumer 能够刷新本地缓存。
当然,不同的注册中心可能在实现原理上会略有差异。
- 例如说,Eureka 注册中心,并不提供通知功能,而是 Eureka Client 自己定期轮询,实现本地缓存的更新。
另外,Provider 和 Consumer 是角色上的定义,一个服务同时即可以是 Provider 也可以作为 Consumer。
- 例如说,优惠劵服务可以给订单服务提供接口,同时又调用用户服务提供的接口。
三个角色交互如下图所示:

常见实现工具
- Nacos:同时支持 CP 和 AP 架构 。一般新的平台建议直接集成Nacos,除了能做注册中心,也可以作为分布式配置中心,比 Sping Cloud Config 更好用。是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
- 优点:
- 适合阿里巴巴生态系统和Spring Cloud。
- 支持几乎所有主流类型的服务的发现、配置和管理,更加适合云原生应用场景。
- 提供了简洁易用的UI界面,帮助管理所有的服务和应用的配置。
- 支持数据持久化,避免了数据的丢失。
- 还提供包括配置版本跟踪、金丝雀发布、一键回滚配置、以及客户端配置更新状态跟踪等在内的一系列开箱即用的配置管理特性。
- 缺点:需要单独运行 Nacos 应用。是阿里巴巴内部使用的产品,对于一些特定的业务场景可能需要进行定制化开发。
- 优点:
- Euerka:是Netflix开源的一款提供服务注册和发现的产品。
- 优点: 可以很好地与其他Spring Cloud组件进行集成,与其他组件一起在 Spring Cloud 项目中运行。适合使用Spring Boot开发的微服务,使用和配置简单。
- 还有一个自我保护的机制,当Eureka Server节点在短时间内丢失过多客户端时,会进入自我保护模式,不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。
- 缺点: 自我保护模式可能会让客户端获取到不可用的服务实例信息。另外,不支持跨语言,只能在Java环境中使用。不支持配置中心。
- 优点: 可以很好地与其他Spring Cloud组件进行集成,与其他组件一起在 Spring Cloud 项目中运行。适合使用Spring Boot开发的微服务,使用和配置简单。
- Consul:从整体上看功能更加完备和均衡。具有开箱即可、部署方便的特点。
- 优点: 支持健康检查,可以防止向失败的服务发送请求。支持多数据中心,使其在构建更大规模的分布式系统时具有优势。
- 缺点: 一些高级功能的使用和配置相对复杂。
- ZooKeeper:在
Dubbo中使用比较多。是Apache的一个开源项目。- 优点: 提供了一种中心化的服务,高可用性、强一致性、分布式配置管理、以及良好的社区支持。
- 缺点: 资源消耗较高、复杂的集群部署和维护。CP特性使其在出现网络分区时可能无法提供服务。另外,API使用起来相对复杂,学习成本较高。
- ETCD:开源的、基于Raft协议的分布式键值存储系统。
- 优点: 使用Raft协议,保证了数据的一致性。支持SSL,可以保证数据的安全性。
- 缺点: 性能相比Zookeeper和Consul要差一些。
Nacos、Eureka 的区别
- 功能范围:Nacos不仅提供了服务发现和注册的核心功能,还额外集成了配置管理和消息总线等特性,使其成为一个更为全面的服务管理平台。界面简洁易用。相比之下,Eureka主要聚焦于服务发现与注册,简单易用,功能较为单一。
- 健康检查机制:Nacos采用健康检查机制来监控服务实例的状态,相比Eureka的心跳检测机制,在服务健康状况的判定上可能更为精确和灵活。
- Eureka 主要依赖客户端的(被动)心跳机制来判断服务实例的健康状态,当连续几次心跳未收到时,Eureka Server 将默认服务实例下线。
- Nacos 对服务实例进行了区分,分为:
- 临时实例(ephemeral):采用与 Eureka 类似的基于心跳的健康检查机制,若心跳超时,则服务实例将被移除。
- 服务实例(持久实例):Nacos Server 不仅依赖心跳,还会主动发起健康检查,确保服务的可用性,即使服务实例没有心跳响应,也不会立即从列表中移除,但会标记为不健康。
- CAP 理论、高可用性:Nacos支持配置多个注册中心实例,显著提高了系统的可靠性和容错能力,特别适合多数据中心的部署场景。Eureka虽然也可以通过外部手段实现类似功能,但原生支持度不如Nacos。
- Eureka 在设计上倾向于 AP 模型,牺牲了一定的一致性,优先保证系统的高可用性和分区容错性。在某些情况下,即使服务实例已经不可用,Eureka 仍可能在短时间内保留失效实例的信息,以防网络分割情况下的数据丢失。
- Nacos 提供了更加灵活的选择,可以根据配置支持 CP 模式、AP 模式。在 CP 模式下,Nacos 可能会在牺牲部分可用性的情况下保证数据一致性。
- 数据一致性要求:如果对服务实例的状态一致性有较高要求,例如希望服务消费者尽可能避免调用已经失效的服务实例,那么可以选择支持 CP 模式的 Nacos。
- 发展与维护状态、社区活跃度和技术支持:
- Eureka则是Netflix开源的,随着Eureka 1.X停止维护以及Eureka 2.0开源计划的不明朗(Eurak2.0之后已经停止开源),
- Nacos 由阿里开源,作为持续更新且拥有活跃社区支持的项目,展现出更高的稳定性和发展前景。在2.0版本之后更是优化了架构和数据模型,提升了性能和稳定性,并提供了丰富的插件扩展机制。也有着庞大的用户群体和技术支持,尤其在中国企业级应用中有较高的市场份额。
- 开源协议与商业友好性:Nacos采用
Apache 2.0许可证,对商业使用非常友好,没有潜在的协议变更风险。相比之下,Consul的开源协议变更历史和潜在的商业使用限制,使得部分用户考虑迁移到Nacos以降低风险。
综上所述,Nacos在功能丰富性、系统稳定性、多数据中心支持以及开源协议的商业友好性等方面,相较于Eureka展现出明显优势,更适合现代复杂分布式系统的需求。
综上所述,选择 Nacos 或 Eureka 应根据项目的具体需求、团队的技术背景以及对一致性和可用性的权衡等因素综合考虑。随着技术的发展,两者的功能也在不断迭代和增强,所以在做出决策时,建议关注最新的版本特性。
Nacos
是
Dynamic Naming and Configuration Service的缩写,动态命名和配置服务。正如其名,Nacos 是阿里开源的注册中心 + 配置中心服务。
Nacos 是阿里巴巴开源的项目,帮助快速实现动态服务发现、服务配置、服务元数据及流量管理。更敏捷和容易地构建、交付和管理微服务平台。
- 目前,Nacos 对 Spring、Spring Boot、Spring Cloud、Dubbo 提供了非常好的支持,已经有蛮多大型互联网公司正在使用。
Nacos 特性
Nacos 具有如下特性:
- 支持(基于DNS和基于RPC的)服务发现,
- 服务发现是微服务架构体系中最关键的组件之一。如果尝试着用手动的方式来给每一个客户端来配置所有服务提供者的服务列表是一件非常困难的事,而且也不利于服务的动态扩缩容。
- Nacos Discovery 可以将服务自动注册到 Nacos 服务端,并且能够动态感知和刷新某个服务实例的服务列表。
- 除此之外, 也将服务实例自身的一些元数据信息-例如 host,port, 健康检查URL,主页等内容注册到 Nacos。
- 健康监测:支持对服务的实时健康检查,阻止向不健康的主机或服务实例发送请求。
- 动态配置服务(配置中心):可以以中心化、外部化和动态化的方式,管理所有环境的应用配置和服务配置;有图形界面。
- 动态 DNS 服务:支持权重路由,可以更容易地实现中间层负载均衡、更灵活的路由策略、流量控制以及数据中心内网的简单DNS解析服务。
- 服务及其元数据管理:支持(从微服务平台建设的视角)管理(数据中心的)所有服务及元数据。

部署
使用
- 使用bin目录下的
startup.cmd -m standalone启动Nacos服务, - 访问地址:http://localhost:8848/nacos/,默认账号密码都是 nacos。
安装
见文档。
单机部署
最简模式
略
用 MySQL 对配置持久化
其中,MySQL 用于 Nacos 对配置的持久化。
- 初始化数据库:在
conf目录下,提供了 MySQL 数据库初始化脚本nacos-mysql.sql。 - 配置数据库连接:修改
conf/application.properties配置文件,在尾部额外增加 MySQL 数据库配置。

集群部署
在生产环境下,需要搭建 Nacos 集群,确保高可用。如,搭建单机部署一个 Nacos 服务。
- 一共是 Nginx、Nacos、MySQL 三层,每一层都需要做高可用。

复制 nacos 文件
将「2. 单机部署」 的 nacos 文件,复制 nacos-01、nacos-02、nacos-03 三个文件夹,用于搭建三个 Nacos 节点。
配置服务器地址
因为是在本机启动三个 Nacos 服务,所以需要修改其端口,保证能够启动。
- 生产环境下,请将 Nacos 多个节点部署到多个服务器,保证 Nacos 的高可用。
在 conf/application.properties 配置文件,修改 server.port 配置项,可以修改 Nacos 服务器端口。
nacos-01对应 18848 端口。nacos-02对应 28848 端口。nacos-03对应 38848 端口。
配置 Nacos 集群
在 nacos-01、nacos-02、nacos-03 三个文件夹中,在 conf/cluster.conf 配置文件,配置一个 Nacos 集群的所有节点。
- 每一行为 Nacos 节点的服务器地址,格式为
ip:port。 - 注意,不要使用
127.0.0.1这个 IP 地址,因为 Nacos 获取的是外部 IP。因此,这里使用的是192.168.3.44。
通过该配置文件,每个 Nacos 服务可以知道集群中的其它 Nacos 节点。
1 | |
启动 Nacos 服务
启动三个 Nacos 服务。
- 执行
sh nacos-01/bin/startup.sh命令,启动 Nacos 节点 01。 - 执行
sh nacos-02/bin/startup.sh命令,启动 Nacos 节点 02。 - 执行
sh nacos-03/bin/startup.sh命令,启动 Nacos 节点 03。
搭建 Nginx 集群
配置转发:搭建完成后,配置 Tengine 配置文件 conf/nginx.conf 如下,增加对 Nacos 服务的负载均衡。主要配置如下:
1 | |
后续,应用中可以直接使用该 Nginx 负载均衡的地址。
- 当然,推荐给 Nginx 绑定一个域名,这样未来 Nginx 服务及时迁移服务器,对于应用也是可以透明的,无需做任何改动。
- 例如说,将 http://nacos.iocoder.cn 转发到 Nginx 服务上。
集成到 Spring Boot
目前感觉,在 Spring Boot 项目中使用 Nacos 作为注册中心,貌似场景并不多。
更多的采用以 Spring Cloud 作为基础选型,可以考虑使用 spring-cloud-alibaba-nacos-discovery 项目。
作为注册中心
配置文件
在 application.yml 中,添加 Nacos 配置。
spring.application.name配置项:应用名。- 默认情况下,如果不设置
nacos.discovery.register.service-name配置项,Spring Boot 注册到 Nacos 的服务名为它。
- 默认情况下,如果不设置
nacos.discovery配置项:
1 | |
命名空间:用于进行租户粒度的配置隔离。
- 不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。
- 常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
- 也就是说,如果多个环境共享同一个 Nacos 服务,可以通过
namespace来区分正式、预发布、UAT、开发等环境。虚拟集群:同一个服务下的所有服务实例组成一个默认集群, 集群可以被进一步按需求划分,划分的单位可以是虚拟集群。
ConsumerController
创建 ConsumerController 类,模拟 Consumer 调用「3.3 ProviderController」提供示例 API 接口。
友情提示:通过直接使用当前 Spring Boot 示例,来模拟 Consumer 角色,方便简洁。
namingService属性,NamingService 对象,用于调用 Nacos 作为命名服务提供的 API。- 不过它比较特殊,需要通过
@NacosInjected注解,来进行注入到 Bean 中。 - 手动编码获取实例
- 不过它比较特殊,需要通过
1 | |
作为配置中心
略
集成到 Spring Cloud
作为注册中心
Spring Cloud Alibaba 提供的 Spring Cloud Alibaba Nacos Discovery 组件,基于 Spring Cloud 的编程模型,接入 Nacos 作为注册中心,实现服务的注册与发现。
步骤如下:
- 首先,搭建一个服务提供者
demo-provider,注册服务到 Nacos 中。 - 然后,搭建一个服务消费者
demo-consumer,从 Nacos 获取到demo-provider服务的实例列表,选择其中一个示例,进行 HTTP 远程调用。
搭建服务提供者
依赖
- 如果要使用Spring Cloud Alibaba 的组件都需要在pom.xml中添加如下的配置;
1 | |
配置文件
创建 application.yaml 配置文件,添加 Nacos Discovery 配置项。
- 重点看
spring.cloud.nacos.discovery配置项,它是 Nacos Discovery 配置项的前缀,对应 NacosDiscoveryProperties 配置项。
1 | |
ProviderApplication
创建 DemoProviderApplication 类,创建应用启动类,并提供 HTTP 接口。
- 添加
@EnableDiscoveryClient注解:开启 Spring Cloud 的注册发现功能。- 不过从 Spring Cloud Edgware 版本开始,实际上已经不需要添加此注解,只需要引入 Spring Cloud 注册发现组件,就会自动开启注册发现的功能。
拓展小知识:在 Spring Cloud Common 项目中,定义了 DiscoveryClient 接口,作为通用的发现客户端,提供读取服务和读取服务列表的 API 方法。而想要集成到 Spring Cloud 体系的注册中心的组件,需要提供对应的 DiscoveryClient 实现类。
例如说,Spring Cloud Alibaba Nacos Discovery 提供了 NacosDiscoveryClient 实现,Spring Cloud Netflix Eureka 提供了 EurekaDiscoveryClient 实现。
如此,所有需要使用到的地方,只需要获取到 DiscoveryClient 客户端,而无需关注具体实现,保证其通用性。
ProviderController
搭建服务消费者
整个项目的代码,和服务提供者是基本一致的。
注意,服务消费者和服务提供者是一种角色的概念,本质都是一种服务,都是可以注册自己到注册中心的。
配置文件
创建 application.yaml 配置文件,添加相应配置项。
- 和服务提供者的基本一致,主要是将配置项目
spring.application.name修改为demo-consumer、改端口 port。
1 | |
ConsumerApplication
创建 DemoConsumerApplication 类,创建应用启动类,Service 调用服务提供者,(or 并提供一个的 HTTP 接口)。
- ①
@EnableDiscoveryClient注解,因为已经无需添加,所以进行了注释。 - ② RestTemplateConfiguration 配置类,创建 RestTemplate Bean。RestTemplate 是 Spring 提供的 HTTP 调用模板工具类,可以方便稍后调用服务提供者的 HTTP API。
1 | |
ConsumerController
从上面的类中拆分出来。
③ TestController 提供了 /hello 接口,用于调用服务提供者的 /demo 接口。
discoveryClient属性,DiscoveryClient 对象,服务发现客户端。这里注入的不是 Nacos Discovery 提供的 NacosDiscoveryClient,保证通用性。未来如果不使用 Nacos 作为注册中心,而是使用 Eureka 或则 Zookeeper 时,则无需改动这里的代码。loadBalancerClient属性,LoadBalancerClient 对象,负载均衡客户端。稍后我们会使用它,从 Nacos 获取的服务demo-provider的实例列表中,选择一个进行 HTTP 调用。
拓展小知识:在 Spring Cloud Common 项目中,定义了LoadBalancerClient 接口,作为通用的负载均衡客户端,提供从指定服务中选择一个实例、对指定服务发起请求等 API 方法。而想要集成到 Spring Cloud 体系的负载均衡的组件,需要提供对应的 LoadBalancerClient 实现类。
例如说,Spring Cloud Netflix Ribbon 提供了 RibbonLoadBalancerClient 实现。
如此,所有需要使用到的地方,只需要获取到 DiscoveryClient 客户端,而无需关注具体实现,保证其通用性。不过貌似 Spring Cloud 体系中,暂时只有 Ribbon 一个负载均衡组件。
当然,LoadBalancerClient 的服务的实例列表,是来自 DiscoveryClient 提供的。
1 | |
测试
- 访问服务消费者的 http://127.0.0.1:28080/hello?name=yudaoyuanma 接口,返回结果为
"consumer:provider:yudaoyuanma"。说明,调用远程的服务提供者成功。 - 关闭服务提供者后,再次访问 http://127.0.0.1:28080/hello?name=yudaoyuanma 接口,返回结果为报错提示
"获取不到实例",说明我们本地缓存的服务demo-provider的实例列表已刷新,没有任何实例。
负载均衡功能:
由于运行了两个nacos-user-service(服务提供方注册),而nacos-ribbon-service(服务消费者)默认会去调用它的接口。
多次调用接口:http://localhost:8308/user/1 ,可以发现两个nacos-user-service的控制台交替打印如下信息。
1 | |
作为配置中心
参见:Spring Cloud Alibaba 配置中心 Nacos 入门
配置优先级:(由高至低?)
bootstrap.yml:对客户端连接 Nacos 配置中心通用环境进行配置。:配置 Nacos 配置中心开发环境的配置,如地址端口等。bootstrap-{profile}.yml- Nacos 配置中心:在Nacos页面中添加配置信息。支持简单的配置对比、版本对比。
:从配置中心获取配置,覆盖或补充本地配置。application.yml:根据激活的Profile加载,覆盖application-{profile}.ymlapplication.yml中的相应配置。application-online.yml。
依赖
-
在客户端添加依赖
1
2
3
4
5
6
7
8<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
本地配置文件
-
bootstrap.yml:对客户端连接 Nacos 配置中心通用环境进行配置。1
2
3
4
5
6
7#server: #port: 9101 # spring: profiles: active: dev application: name: mall-admin -
:配置 Nacos 配置中心开发环境的配置,如地址端口等;bootstrap-{profile}.yml1
2
3
4
5
6
7
8
9
10
11
12
13
14spring: cloud: nacos: discovery: server-addr: localhost:8848 #Nacos地址 config: server-addr: localhost:8848 #Nacos地址 file-extension: yaml #获取yaml格式的配置 # Nacos中的dataid的组成格式,及与SpringBoot配置文件中的属性对应关系: # ${application.name}-${profiles.active}.${cloud.nacos.config.file-extension} # 比如,要获取应用名称为`nacos-config-client`的应用在`dev`环境下的`yaml`配置,dataid如下: # nacos-config-client-dev.yaml
Nacos 配置中心
-
配置中心:在Nacos页面中添加配置信息。支持简单的配置对比、版本对比。
-
Data ID:
nacos-config-client-dev.yaml, -
Group:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18spring: datasource: url: jdbc:mysql://localhost:3306/mall?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false username: root password: root data: redis: host: localhost # Redis服务器地址 database: 0 # Redis数据库索引(默认为0) port: 6379 # Redis服务器连接端口 password: # Redis服务器连接密码(默认为空) timeout: 3000ms # 连接超时时间(毫秒) logging: level: root: info com.macro.mall: info logstash: host: localhost
-
-
:从配置中心获取配置,覆盖或补充本地配置。application.yml1
2
3
4
5server: port: 9101 # spring: #profiles: #active: dev -
:根据激活的Profile加载,覆盖application-{profile}.ymlapplication.yml中的相应配置。application-online.yml
ConfigClientController
创建 ConfigClientController,从Nacos配置中心中获取配置信息:
@RefreshScope:实现动态刷新配置,用来自动刷新Bean中的属性配置。可以让 Spring Boot 应用程序在运行时重新加载配置。这意味着可以在不停止和重新启动应用程序的情况下更改配置。- 当在Nacos页面上修改配置信息并发布后,再次调用查看配置的接口,就会发现配置已经刷新。
- Nacos和Consul一样都支持动态刷新配置。
1 | |
启动
- 启动 nacos-config-client,调用接口查看配置信息:http://localhost:9101/configInfo
1 | |
集成到 Dubbo
Nacos 集成到 Dubbo 项目中:
- 作为注册中心,通过
dubbo-registry-nacos项目,可见《芋道 Spring Boot Dubbo 入门》的「6. 整合 Nacos」小节。 - 作为配置中心,通过
dubbo-metadata-report-nacos项目,TODO
概念
基于如下两篇文档梳理,推荐后续也看看:
数据模型和服务领域模型整理如下图所示:

数据模型
Nacos 数据模型 Key 由三元组唯一确认。
- 作为注册中心时,Namespace + Group + Service
- 作为配置中心时,Namespace + Group + DataId

Namespace 命名空间
用于进行租户粒度的配置隔离。默认为 public(公共命名空间)。
不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
稍后在「6. 多环境配置」小节中,我们会通过 Namespace 隔离不同环境的服务。
4.1.2 Group 服务分组
不同的服务可以归类到同一分组。默认为 DEFAULT_GROUP(默认分组)。
4.1.3 Service 服务
例如说,用户服务、订单服务、商品服务等等。
4.2 服务领域模型
Service 可以进一步细拆服务领域模型,如下图:

我们来看看图中的每个“节点”的概念。
4.2.1 Instance 实例
提供一个或多个服务的具有可访问网络地址(IP:Port)的进程。
我们以「3.1 搭建服务提供者」小节来举例子:
- 如果我们启动一个 JVM 进程,就是服务
demo-provider下的一个实例。 - 如果我们启动多个 JVM 进程,就是服务
demo-provider下的多个实例。
4.2.2 Cluster 集群
同一个服务下的所有服务实例组成一个默认集群(Default)。集群可以被进一步按需求划分,划分的单位可以是虚拟集群。
例如说,我们将服务部署在多个机房之中,每个机房可以创建为一个虚拟集群。每个服务在注册到 Nacos 时,设置所在机房的虚拟集群。这样,服务在调用其它服务时,可以通过虚拟集群,优先调用本机房的服务。如此,在提升服务的可用性的同时,保证了性能。
4.2.3 Metadata 元数据
Nacos 元数据(如配置和服务)描述信息,如服务版本、权重、容灾策略、负载均衡策略、鉴权配置、各种自定义标签 (label)。
从作用范围来看,分为服务级别的元信息、集群的元信息及实例的元信息。
Health Check 健康检查
以指定方式检查服务下挂载的实例的健康度,从而确认该实例是否能提供服务。根据检查结果,实例会被判断为健康或不健康。
对服务发起解析请求时,不健康的实例不会返回给客户端。
健康保护阈值
为了防止因过多实例不健康导致流量全部流向健康实例,继而造成流量压力把健康实例实例压垮并形成雪崩效应,应将健康保护阈值定义为一个 0 到 1 之间的浮点数。
当域名健康实例占总服务实例的比例小于该值时,无论实例是否健康,都会将这个实例返回给客户端。这样做虽然损失了一部分流量,但是保证了集群的剩余健康实例能正常工作。
多环境配置
同一个服务,我们会部署到开发、测试、预发布、生产等环境中,那么我们需要在项目中,添加不同环境的 Nacos 配置。一般情况下,开发和测试使用同一个 Nacos,预发布和生产使用另一个 Nacos。那么针对相同的 Nacos,我们怎么实现不同环境的隔离呢?
实际上,Nacos 开发者已经告诉我们如何实现了,通过 Nacos Namespace 命名空间。
搭建服务提供者
搭建服务消费者
监控端点
Nacos Discovery 基于 Spring Boot Actuator,提供了自定义监控端点 nacos-discovery,获取 Nacos Discovery 配置项,和订阅的服务信息。
同时,Nacos Discovery 拓展了 Spring Boot Actuator 内置的 health 端点,通过自定义的 NacosDiscoveryHealthIndicator,获取和 Nacos 服务器的连接状态。
友情提示:对 Spring Boot Actuator 不了解的胖友,可以后续阅读《芋道 Spring Boot 监控端点 Actuator 入门》文章。
搭建一个 Nacos Discovery 监控端点的示例。步骤如下:
- 首先,搭建一个服务提供者
demo-provider,注册服务到 Nacos 中。 - 然后,搭建一个服务消费者
demo-consumer,调用服务提供者demo-provider提供的 HTTP 接口。同时,配置开启服务消费者的 Nacos Discovery 监控端点。 - 最后,访问服务消费者的 Nacos Discovery 监控端点,查看下返回的监控数据。
Spring Cloud Eureka
Spring Cloud Eureka是Spring Cloud Netflix 子项目的核心组件之一,主要用于微服务架构中的服务治理(服务注册与发现)。是 Spring Cloud 微服务框架默认的(也是推荐的)服务注册中心。
在微服务架构中往往会有一个注册中心,每个微服务都会向注册中心去注册自己的地址及端口信息,注册中心维护着服务名称与服务实例的对应关系。每个微服务都会定时从注册中心获取服务列表,同时汇报自己的运行情况,这样当有的服务需要调用其他服务时,就可以从自己获取到的服务列表中获取实例地址进行调用,Eureka实现了这套服务注册与发现机制。- Netflix开源的服务发现组件,基于REST服务开发,主要用于实现服务定位,以实现中间层服务器的负载均衡和故障转移,遵循着CAP理论中的A(可用性)、P(分区容错性)。
- 服务注册:Eureka 作为服务注册中心,服务提供者启动时向 Eureka Server 注册自身的服务信息(包括服务名、IP 地址、端口号等)。Eureka Server 维护一个服务注册表,存储所有已注册服务的信息。
- 还有一个自我保护的机制,当Eureka Server节点在短时间内丢失过多客户端时,会进入自我保护模式,不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。
- 服务发现:客户端(消费者)通过请求 Eureka Server 获取服务提供者的列表,并基于这些信息实现负载均衡调用。Eureka Client 定期发送心跳到 Eureka Server 来更新其服务状态,维持服务实例的有效性。
- 不支持配置中心?用 Spring Cloud Config 支持配置中心
分为Server和Client两部分:
- Eureka Server 作为服务的注册中心,其他的微服务就相当于客户端,注册到注册中心中。eureka client 既可以作为服务的生产者,又可以作为服务的消费者。
- 与注册的客户端保持心跳,并将服务名称映射到(按服务名称查找服务的)客户端的主机名。
- Spring Cloud使用注解的方式提供了Eureka服务端(
@EnableEurekaServer)和客户端(@EnableEurekaClient)。

搭建 Eureka Server 注册中心
使用IDEA来创建SpringCloud应用
-
创建一个eureka-server模块,并使用Spring Initializer初始化一个SpringBoot项目,填写应用信息,选择需要的 SpringCloud Eureka 组件进行创建。
-
创建完成后会发现pom.xml文件中已经有了eureka-server的依赖
1 | |
- 在启动类上添加
@EnableEurekaServer注解来启用Euerka注册中心功能
1 | |
- 添加Java配置WebSecurityConfig
默认情况下添加SpringSecurity依赖的应用每个请求都需要添加CSRF token才能访问,Eureka客户端注册时并不会添加,所以服务端需要配置/eureka/**路径不需要CSRF token。
1 | |
配置 Eureka Server
-
在配置文件application.yml中添加Eureka注册中心的配置
-
- Eureka服务器的默认端口是8761。 - 默认的 url 是http://localhost:8761/eureka/,因此defaultZone处的配置可以省略。
1 | |
搭建Eureka注册中心集群(负载均衡功能)
搭建两个注册中心
由于所有服务都会注册到注册中心去,服务之间的调用都是通过从注册中心获取的服务列表来调用,注册中心一旦宕机,所有服务调用都会出现问题。所以我们需要多个注册中心组成集群来提供服务,下面将搭建一个双节点的注册中心集群。
- 给eureka-sever添加配置文件application-replica1.yml配置第一个注册中心
1 | |
- 给eureka-sever添加配置文件application-replica2.yml配置第二个注册中心
1 | |
这里通过两个注册中心互相注册,搭建了注册中心的双节点集群,由于defaultZone使用了域名,所以还需在本机的host文件中配置一下。
- 修改本地host文件
1 | |
运行Eureka注册中心集群
在IDEA中我们可以通过使用不同的配置文件来启动同一个SpringBoot应用。
- 添加两个配置,分别以application-replica1.yml和application-replica2.yml来启动eureka-server
从原启动配置中复制一个出来

配置启动的配置文件

- 使用IDEA的Run Dashboard(Service 面板)来运行SpringCloud应用
- 启动两个eureka-server,访问其中一个注册中心http://replica1:8002/发现另一个已经成为其备份

搭建 Eureka 客户端(并注册到注册中心)
- 新建一个eureka-client模块,并在pom.xml中添加如下依赖。
1 | |
- 在启动类上添加
@EnableDiscoveryClient注解表明是一个Eureka客户端。 -
或
@EnableEurekaClient注解,告诉Spring Boot明确使用Spring Netflix Eureka进行服务发现。 - 注意,如果类路径classpath具有上面的依赖项,则这俩注解是可选的。
1 | |
配置 Eureka Client
- 在配置文件application.yml中添加Eureka客户端的配置
- 有登录认证的注册中心地址格式
1 | |
1 | |
-
查看注册中心http://localhost:8001/发现Eureka客户端已经成功注册
-
以该配置文件启动后,访问任意一个注册中心节点(8002、8003)都可以看到eureka-client

发现REST服务
各个客户端可能需要相互访问,首先需要彼此知道对方存在,即发现REST服务,这里介绍2种实现方式。
- EurekaClient:
- 代码中注入了
EurekaClient实体类,需要延迟加载EurekaClient,因此这里使用@Lazy注解。 - 通过
EurekaClient实例,可以接收一个以service-name命名的服务信息,作为Application对象。根据此对象获取(该服务的)所有实例的列表,选择一个合适的实例,然后使用此实例获取主机名和端口。
- 代码中注入了
- DiscoveryClient:
- 代码中注入了DiscoveryClient实体类,需要延迟加载DiscoveryClient,因此这里使用@Lazy注解。
- 通过
DiscoveryClient实例,可以接收一个以service-name命名的服务信息,返回(该服务的)所有实例的列表,选择一个合适的实例,然后使用此实例获取主机名和端口。
这样,可以对任何http客户端发出标准请求。
使用REST服务
当使用RestTemplate来调用其他服务时,Ribbon可以很方便的实现负载均衡功能。
RestTemplate:是一个HTTP客户端,可以方便的调用HTTP接口,支持GET、POST、PUT、DELETE等方法。
Eureka的常用配置
1 | |
Spring Cloud Consul
Consul 提供了微服务系统中的服务治理、配置中心、控制总线等功能。每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网格,总之提供了一种完整的服务网格解决方案。
具有如下特性:
- 支持服务治理:作为注册中心时,微服务中的应用可以向Consul注册自己,并且可以从Consul获取其他应用信息;
- 支持客户端负责均衡:包括
Ribbon和Spring Cloud LoadBalancer; - 支持
Zuul:当Zuul作为网关时,可以从Consul中注册和发现应用; - 支持分布式配置管理:作为配置中心时,使用键值对来存储配置信息;还支持动态刷新。
- 支持控制总线:可以在整个微服务系统中通过 Control Bus 分发事件消息。
- 与Docker容器可以无缝集成。

负载均衡功能
由于我们运行了两个consul-user-service,而consul-ribbon-service默认会去调用它的接口,我们调用consul-ribbon-service的接口来演示下负载均衡功能。
多次调用接口:http://localhost:8308/user/1 ,可以发现两个consul-user-service的控制台交替打印如下信息。
1 | |
使用Consul作为配置中心
动态刷新配置
我们只要修改下Consul中的配置信息,再次调用查看配置的接口,就会发现配置已经刷新。
- 回想下在使用Spring Cloud Config的时候,我们需要调用接口,通过Spring Cloud Bus才能刷新配置。
- Consul使用其自带的Control Bus 实现了一种事件传递机制,从而实现了动态刷新功能。
Spring Cloud Zookeeper
操作Zookeeper的工具包,用于使用zookeeper方式的服务注册和发现。