学习顺序建议
1.先理解「硬编码调用为什么不行」,明白注册中心诞生的意义;
2.学习 Eureka,掌握经典注册中心工作原理;
3.学习 LoadBalancer 负载均衡原理;
4.学习 Nacos,同时掌握注册 + 配置两大功能;
5.最后对比 Eureka 与 Nacos 选型差异,理解为什么生产环境普遍选用 Nacos。
一、微服务服务调用的原始方案与存在的常见问题
这是微服务场景下订单服务调用商品服务的基础实现:
- 查询订单信息,拿到订单中的
productId; - 通过
RestTemplate拼接固定地址http://127.0.0.1:9090/product/{id}远程调用商品服务; - 获取商品实体
ProductInfo,塞入订单实体OderInfo中,实现订单携带商品详情返回。


可能会出现一些问题,比如接口公开安全性,商品服务一旦更换 IP、端口、部署多实例,代码直接失效;无法实现集群负载均衡。
二.引入注册中心后的微服务架构流程
完整流程
- 服务注册 :服务提供者启动时,将自身服务名称、IP、端口信息上报给注册中心保存。
- 服务发现:服务消费者启动 / 发起调用前,向注册中心查询「目标服务名称」对应的可用 IP 地址列表。
- 远程调用:消费者拿到提供者实例地址后,直接发起远程调用;结合负载均衡策略,可轮流调用多个服务实例。
- 注册中心职责:维护「服务名称 ↔ 实例 IP 地址」的映射关系,同时检测服务健康状态,剔除宕机节点。

主流注册中心组件
Nacos、Eureka、Consul、ZooKeeper。
CAP理论是分布式系统最基础最关键的理论,
C:强一致性,何时访问结果一致,
A:可用性,对于请求都有响应,但是可能是错误的
P:分区容错性:在网络分区情况下依然可以提供服务
一致性:客户端向数据集群发送一个数据修改的请求,数据集群回复一个响应,响应分为两种,一种是主库收到请求,但数据未同步,随着时间推移会达到一致,另一种是主库收到请求,数据已经同步从库。
强一致性:无论何时,主库从库对外提供的服务保持一致。
弱一致性:随着时间推移最终会达到一致。

因为P是必须保证的,所以A与P只能实现一个
三、Eureka
搭建注册中心
1.创建项目

2.pom加入Eureka依赖
<!--Eureka服务端--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
3.配置文件,加入Eurka相关配置
server: port: 10010 spring: application: name: eureka-server eureka: instance: hostname: localhost client: fetch-registry: false # 表示是否从Eureka Server获取注册信息,默认为true.因为这是一个单点的Eureka Server,不需要同步其他的Eureka Server节点的数据,这里设置为false register-with-eureka: false # 表示是否将自己注册到Eureka Server,默认为true.由于当前应用就是Eureka Server,故而设置为false. service-url: # 设置与Eureka Server的地址,查询服务和注册服务都需要依赖这个地址 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
4.启动类,开启Eurka功能


服务注册:
1.加入Eureka依赖
<!-- 正确:Eureka客户端,用来注册到注册中心 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
2.修改配置信息
server: port: 9090 spring: application: name: product-service datasource: url: jdbc:mysql://localhost:3306/cloud_product?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*Mapper.xml configuration: # 配置打印 MyBatis 执行的 SQL log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true #自动驼峰转换 eureka: client: service-url: defaultZone: http://127.0.0.1:10010/eureka/
3.启动测试
服务发现:
1.加入Eureka依赖
<!-- 正确:Eureka客户端,用来注册到注册中心 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
2.修改配置信息
server: port: 8080 spring: application: name: order-service datasource: url: jdbc:mysql://localhost:3306/cloud_order?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*Mapper.xml configuration: # 配置打印 MyBatis 执行的 SQL log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true #自动驼峰转换 eureka: client: service-url: defaultZone: http://127.0.0.1:10010/eureka/
3.修改远程调用代码

4.启动测试


四、负载均衡
什么是负载均衡
启动了 3 个 product-service 商品服务实例(端口 9090、9091、9092)并注册到注册中心。
订单服务发起远程调用时,始终固定访问 192.168.32.1:9090 这一台实例 ,请求没有分发到另外两台商品节点,集群多实例完全没起到分担压力的作用,也就是没有负载均衡效果。

我们启动多个实例, 希望可以分担其他机器的负荷, 那么如何实现呢?解决方法:
使用
AtomicInteger原子计数器实现轮询算法,每次请求序号自增,对实例总数取模选中不同服务节点。



轮流请求

请求被均衡的分配在了不同的实例上, 这就是负载均衡
负载均衡分为服务端负载均衡和客⼾端负载均衡,服务器负载均衡是在服务端进行负载均衡算法分配,客户端负载均衡是在客户端进行负载均衡的算法分配
SpringCloud LoadBalance
- 作用 :Spring Cloud 官方推出的客户端负载均衡组件,用来替代已经停止维护的 Netflix Ribbon,是目前 SpringCloud 体系默认负载均衡方案。
- 客户端负载均衡含义 :负载均衡逻辑运行在服务消费者(订单服务)内部,而非独立网关;消费者本地缓存服务实例列表,本地算法挑选节点转发请求。
- 适配:兼容 Nacos/Eureka/Consul 所有注册中心,同时支持同步 RestTemplate、响应式 WebClient、OpenFe
1.添加注解

2.修改远程调用代码,把IP和端口号改成应用名

负载均衡策略
负载均衡策略是⼀种思想, ⽆论是哪种负载均衡器, 它们的负载均衡策略都是相似的. Spring Cloud LoadBalancer 仅⽀持两种负载均衡策略: 轮询策略 和 随机策略
Spring Cloud LoadBalancer 默认负载均衡策略是 轮询策略, 实现是 RoundRobinLoadBalancer, 如果
服务的消费者如果想采⽤随机的负载均衡策略, 也⾮常简单.
- 定义随机算法对象, 通过 @Bean 将其加载到 Spring 容器中

- 使⽤ @LoadBalancerClient 或者 @LoadBalancerClients 注解,只有⼀个服务提供者, 所以使⽤@LoadBalancerClient

五、Nocos
Nocas的安装
windows
1.下载地址 https://github.com/alibaba/nacos/releases/tag/2.2.3
下载zip文件解压
2.修改单机模式:修改startup.cmd文件

3.启动成功后, 访问Nacos链接: http://IP:port/nacos

Linux:
1.上传zip文件并且解压:

2.如果需要,修改端口号
3.启动Nacos
命令:bash startup.sh -m standalone
启动成功后, 访问Nacos链接: http://IP:port/nacos
nacos的使用
1.父工程pom文件引⼊Spring Cloud Alibaba依赖:
<properties>
<spring-cloud-alibaba.version>2022.0.0.0-RC2</spring-cloud-alibaba.version>
</properties>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
2.再order-service和product-service引入nacos依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-loadbalancer</artifactId> </dependency>
3.配置nacos地址
spring:
application:
name: product-service
cloud:
nacos:
discovery:
server-addr: 110.41.51.65:10020
- 修改IP为项⽬名

- 为restTemplate添加负载均衡注解 @LoadBalanced

启动服务
开启nacos负载均衡:
spring:
cloud:
loadbalancer:
nacos:
enabled: true
1.支持服务上线下线
2.服务配置权重
3.同集群优先访问:
spring:
cloud:
nacos: discovery: server-addr: cluster-name: BJ #设置集群名称

Nacos健康检测
一、客户端主动上报机制
-
客户端通过心跳上报方式告知 Nacos 注册中心自身健康状态,默认心跳间隔 5 秒;
-
Nacos 规则:
-
超过 15 秒 未收到心跳 → 将实例标记为不健康;
-
超过 30 秒 未收到心跳 → 直接删除该实例。
-
二、服务端反向探测机制
-
Nacos 主动探测客户端健康状态,默认探测间隔 20 秒;
-
健康检查失败后,实例仅被标记为不健康,不会立刻删除。

服务节点,默认为临时实例,临时实例采用客户端主动上报,非临时实例是服务器反向探测
Nacos会记录每一个实例的IP,端口号以及实例类型,不允许临时实例与非临时实例变化如果修改需要,修改Nacos的相关数据,即删除raft文件夹,nacos\data\protocol\raft。
再修改yml文件
Spring: cloud: nacos: discovery: ephemeral: false # 设置为非临时实例
Nacos环境隔离
企业开发中, ⼀个服务会分为开发环境, 测试环境和⽣产环境.,这些环境是相互隔离的,
Nacos提供了namespace(命名空间)来实现环境的隔离,不同的namaspace的服务不可⻅。
1.创建Namespace

2.配置Namespace
spring:
cloud:
nacos:
discovery:
namespace: 命名空间ID
不同环境不能相互通信:


Nacos配置中心
添加配置获取配置
1.添加配置 在Nacos控制台添加配置项点击创建配置


微服务启动前, 需要先获取nacos中配置, 并与application.yml配置合并. 在微服务运⾏之前, Nacos要求必须使⽤ bootstrap.yml 配置⽂件来配置Nacos Server 地址
2.引入依赖
spring: application: name: product-service cloud: nacos: config: server-addr: 118.31.239.155
spring.application.name 需要和nacos配置管理的Data ID⼀致spring.cloud.nacos.config.server-addr 为Nacos Server的地址
3.编写程序

@Value的配置对应nacos创建的配置内容

测试:

设置命名空间
刚刚明明改改 application.yml 的 namespace为什么bootstrap.yml又再次修改
关键原因:Nacos 配置加载顺序
Spring 加载配置优先级:
bootstrap.yml(最先加载) > application.ymlNacos 配置是在容器启动早期、解析 bootstrap 阶段 就去远程拉取配置; 如果你的namespace写在application.yml里: 拉取 Nacos 配置的时候,程序还没读取到 application.yml 的 namespace,此时默认使用public命名空间拉配置; 等后面读到 application.yml 的 namespace 时,配置早已加载完毕,自然不会切换 dev 命名空间的配置。现象表现
- 服务注册:会按照 application.yml 的 namespace,注册到 dev 命名空间;
- 配置拉取:启动拉配置阶段没读到 dev 命名空间配置,依旧从 public 拉配置。
在bootstrap.yml文件设置namespace,改为dev的命名空间ID




Data ID
dataId 的完整格式如下: {prefix}-{spring.profiles.active}.{file-extension} 1**.prefix**默认为 **spring.application.name** 的值, 也可以通过配置项 **spring.cloud.nacos.config.prefix** **来配置.** 2.**spring.profiles.active** 即为当前环境对应的 profile. 当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 {prefix}.${file
extension}
3.**file-exetension****为配置内容的数据格式,**可以通过配置项
spring.cloud.nacos.config.file-extension 来配置。⽬前只⽀持 properties
和 yaml 类型. 默认为properties.
优先级:product-service-dev.properties > product-service.properties > product-service
删除配置项product-service-dev.properties

删除配置项product-service.properties

六、Nacos与Eureka区别
相同点:都支持服务注册和服务拉取
区别:
1.功能:Nacos额外提供配置中心和DNS服务等功能
2.CAP理论:Eureka遵循AP原则,Nacos可以切换AP与CP原则,默认AP
Nacos根据配置识别CP或者AP模式,如果注册Nacos的Client的节点是临时节点,那么这个Nacos对这个Client节点的效果是AP,反之CP
3.服务发现:Eurca:基于拉模式,Eureka Client 会定期从Server拉服务,有缓存,默认30秒拉一次
Nacos:基于推送模式,服务列表有变化实时推送订阅者,服务器客户端保持心跳连接









