一、认识微服务
1.1 微服务架构演变
- 单体架构: 将业务的所有功能集中在一个项目中开发,打成一个包部署(简单方便,高度耦合,拓展性差,适合小型项目,如学生管理系统);
- 分布式架构: 根据业务功能对系统进行拆分,每个业务模块作为独立项目开发,称为一个服务(松耦合,扩展性好,但架构复杂,难度大,适合大型互连网项目,如京东、淘宝);
- 微服务: 是一种经过良好架构设计的分布式 架构方案(优点: 拆分粒度更小,服务更独立,耦合度更低;缺点: 架构非常复杂,运维、监控、部署难度提高);

1.2 微服务技术对比


1.3 微服务结构---SpringCloud


二、服务拆分
2.1 服务拆分
服务拆分注意事项:
- 不同微服务,不要重复开发相同业务;
- 微服务数据独立,不要方位其他微服务的数据库;
- 微服务可以将自己的业务暴露为接口,共其他微服务调用;
2.2 服务间调用



三、Eureka
3.1 概念
定义: Eureka是Netflix开源、基于REST的服务注册与发现组件,是Spring Cloud微服务架构的核服务治理工具,相当于微服务集群里的动态通讯录/服务注册中心 ;
作用: 主要解决微服务拆分后,服务实例动态扩容/缩容、IP/端口变化、故障下线时,服务之间如何自动寻址、避免硬编码地址、保证调用可靠 的问题;
核心两大组件: Eureka Server(服务注册中心)、Eureka Client(客户端、嵌入微服务)
3.2 核心两大组件
- Eureka Server(服务注册中心)
- 作用: 维护服务注册表,存储所有已注册服务的实例信息(服务名、IP、端口、健康状态);
- 功能: 接受注册、响应查询、心跳检测、自动剔除失效实例、集群数据同步、提供Web管理控制台;
- 部署: 支持单节点/集群(多Server互相复制注册表,保证高可用);
- Eureka Client(客户端、嵌入微服务)
- 服务提供者: 启动时自动注册 自身信息到 Server;每 30 秒发心跳续约(默认),证明存活,一次业务中,被其他微服务调用的服务(提供接口给其他微服务);
- 服务消费者: 启动时拉取全量注册表并本地缓存 ,之后每 30 秒增量更新;用服务名(如 user-service) 调用,不用写死 IP / 端口,一次业务中,调用其他微服务的服务(调用其他微服务提供的接口);
- 内置: 配合 Ribbon 实现客户端负载均衡 (轮询等策略)
注意: 提供者和消费者角色是相对的;

3.3 核心工作流程
一句话:服务注册--->心跳保活--->服务发现--->失效剔除
- 注册: 微服务启动,Client向Server发送注册请求,写入注册表;
- 续约: Client每30秒发心跳,Server超过90秒没有收到心跳,标记DOWN并剔除;
- 发现: 消费者从Server拉取服务列表,本地缓存,按服务名调用;
- 自我保护: 15分钟内心跳丢失>85%,进入保护模式,不剔除任何实例,避免网络抖动误删;
3.4 核心作用
- 解耦地址硬编码: 不用在代码/配置里写死IP:端口,用服务名调用,扩容/迁移/重启都不用改配置;
- 自动健康检查与容错: 自动剔除宕机实例,避免请求打到无效节点,提供系统稳定性;
- 负载均衡与弹性伸缩: 多实例自动加入列表,配合Ribbon做负载均衡,扩容/缩容无感,无需人工干预;
- 服务治理可视化: Web控制台查看所有服务、实例状态、心跳,方便运维监控;
- 高可用保障: Server集群+客户端缓存,即使部分Server挂了,仍可用本地缓存调用;


3.5 适用场景&现状
- 适用: Spring Cloud微服务架构(Java生态)、服务数量多、动态扩缩容、需要服务治理的分布式系统;
- 现状: Netflix已停止维护(进入维护模式),Spring Cloud 2020+ 推荐替代:Nacos、Consul、K8s、Service;
3.6 简单示例(Spring Boot)
Server: 加@EnableEurekaServer,配置端口、集群节点;
Client(提供者/消费者): 加@EnableDiscoveryClient,配置服务名、Server地址;
调用: 用RestTemplate+@LoadBalanced,直接写```http://user-service/getUser\`\`;
搭建eureka服务


服务注册



服务发现

四、Ribbon
4.1 Ribbon是什么
在软件开发领域,尤其是在微服务和Java后端开发中,Ribbon 指的是一个由 Netflix 开源的客户端负载均衡器。
4.2 能解决什么问题
在微服务架构中,一个应用(比如订单服务)往往会部署多个实例来应对高并发和保证高可用。当一个调用方(比如用户服务)需要调用订单服务时,它面对的是一个服务实例列表(如 order-service-1:8080, order-service-2:8080),而Ribbon要解决的问题就是:具体选择哪一个实例来发送请求?。
这个过程就是负载均衡 。与Nginx这种集中式的服务端负载均衡不同,Ribbon实现的是进程内的客户端负载均衡,即负载均衡的逻辑是跑在调用方(客户端)进程里的。
4.3 如何工作的?
Ribbon 的工作流程大致如下:
- 获取服务列表:从服务注册中心(如 Eureka、Nacos)获取目标服务的所有可用实例地址列表。
- 执行负载均衡策略:根据预设的算法(如轮询、随机、响应时间权重等),从列表中"聪明地"选中一个服务实例。
- 发起请求 :将原本包含服务名的请求(如
http://order-service/getOrder),替换为具体的实例地址(如http://192.168.1.100:8080/getOrder)并发送。
4.4 在技术栈中的位置
- 与Spring Cloud的集成 :在Spring Cloud Netflix体系中,Ribbon曾是微服务间调用(RPC)的默认负载均衡组件。即便后来流行的声明式HTTP客户端 OpenFeign,其底层也是依赖Ribbon来实现负载均衡的。
- 现状 :需要注意的是,Netflix已宣布Ribbon进入维护状态 (不再积极开发新特性)。Spring Cloud社区也推出了自己的负载均衡器 Spring Cloud LoadBalancer 作为替代方案。不过,由于其设计经典且应用广泛,理解和学习Ribbon对掌握负载均衡的核心思想依然很有帮助。
4.5 常用负载均衡策略
Ribbon 提供了几种开箱即用的策略:
| 策略名称 | 算法描述 | 适用场景 |
|---|---|---|
| 轮询 (RoundRobin) | 按顺序依次选择服务实例,这是默认策略。 | 服务实例性能相近,请求量均匀的场景。 |
| 随机 (Random) | 随机选择一个可用的服务实例。 | 实例性能差异较大,通过随机性来平衡负载。 |
| 权重响应时间 (WeightedResponseTime) | 根据实例的响应时间动态计算权重,响应越快,被选中的概率越高。 | 实例性能差异明显,希望自动将流量导向性能更优的机器。 |
| 最少并发 (BestAvailable) | 优先选择正在处理的请求数最少的实例。 | 请求处理时间长短不一,需要避免某些实例积压太多请求。 |
| 可用性敏感 (AvailabilityFiltering) | 会过滤掉那些连接失败或并发数过高的"坏"实例。 | 需要高可用性,希望自动避开故障或繁忙的节点。 |
4.6 快速上手示例
在你的Spring Cloud项目中,使用Ribbon非常简单。
首先,确保项目中已经引入了Spring Cloud Netflix Ribbon或Eureka Client的依赖。
然后,在编写RestTemplate的配置时,加上 @LoadBalanced 注解即可:
java
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class AppConfig {
@Bean
@LoadBalanced // 这个注解是关键,它会让RestTemplate自动使用Ribbon进行负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
之后,你就可以在代码中直接通过服务名来调用接口了,Ribbon会自动将其解析为一个具体的服务实例地址。
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class MyService {
@Autowired
private RestTemplate restTemplate;
public String callOrderService() {
// 直接使用服务名 'order-service' 进行调用
String url = "http://order-service/api/order/123";
// RestTemplate会自动利用Ribbon将服务名替换为真实IP和端口
return restTemplate.getForObject(url, String.class);
}
}
4.7 懒加载


五、Nacos
5.1 Nacos是什么
Nacos (读作 /nɑ:kəʊs/)是阿里巴巴开源的一个动态服务发现、配置管理和服务管理平台 。它的名字取自 Na ming(命名)和 Co nfiguration(配置)的前两个字母,末尾的 s 代表 Service(服务)[citation:1]。
简单来说,Nacos 在微服务架构中扮演着两个核心角色:
- 服务注册中心:让服务能够找到彼此
- 配置中心:集中管理所有服务的配置
5.1.1 解决什么问题
在微服务架构中,一个系统往往被拆分成几十甚至上百个独立运行的服务。这些服务需要解决两个核心问题:
| 问题场景 | Nacos 的解决方案 |
|---|---|
| 服务发现问题:订单服务如何知道用户服务的具体 IP 和端口? | 服务注册与发现:服务启动时自动注册到 Nacos,调用方从 Nacos 获取服务实例列表 [citation:7][citation:9] |
| 配置管理问题:修改数据库密码后,如何不重启上百个服务? | 动态配置管理:配置集中存储在 Nacos,变更实时推送到所有服务,无需重启 [citation:1][citation:2] |
5.1.2 核心功能详解
- 服务注册:微服务启动时,将自己的 IP、端口等信息注册到 Nacos
- 服务发现:服务消费者从 Nacos 获取目标服务的实例列表
- 健康检查:Nacos 通过心跳机制(默认 5 秒一次)检测服务实例健康状态,自动剔除不健康的实例 [citation:7][citation:9]
服务注册流程:
- 服务提供者启动 → 向 Nacos 发送注册请求
- Nacos 记录服务实例信息(IP、端口、服务名)
- 服务消费者订阅服务 → 获取实例列表
- 服务提供者定期发送心跳(5秒/次)维持注册
- 15秒未收到心跳 → 标记为不健康;30秒未收到 → 剔除实例
5.1.3 动态配置管理
- 集中化管理:将所有环境的配置(开发、测试、生产)统一存储在 Nacos
- 实时推送:配置变更后,Nacos 毫秒级推送到所有客户端
- 版本管理:支持配置的历史版本管理和一键回滚 [citation:2][citation:10]
yaml
# 配置示例
Data ID: userservice-dev.yaml
Group: DEFAULT_GROUP
内容:
database:
url: jdbc:mysql://localhost:3306/userdb
username: root
app:
name: user-service
version: 2.0
5.2 服务管理
元数据管理: 为服务实例添加自定义标签(如版本号、环境信息)
流量管理: 支持基于权重的流量分配(例如:v1 版本 90% 流量,v2 版本 10% 流量)
多环境隔离: 通过命名空间(Namespace)实现开发、测试、生产环境的配置和服务隔离
5.2.1 与Spring Cloud集中
Nacos 是 Spring Cloud Alibaba 的核心组件,可以无缝替换 Eureka 和 Spring Cloud Config
- 添加依赖
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
- 配置文件(bootstrap.yml)
yaml
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 # 注册中心地址
config:
server-addr: localhost:8848 # 配置中心地址
file-extension: yaml # 配置文件格式
- 启用服务发现
java
@SpringBootApplication
@EnableDiscoveryClient // 启用服务发现
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
- 动态配置使用
java
@RestController
@RefreshScope // 支持配置动态刷新
public class ConfigController {
@Value("${app.name:default}")
private String appName;
@GetMapping("/config")
public String getConfig() {
return "app.name = " + appName;
}
}
与Eureka比较
| 对比项 | Nacos | Eureka |
|---|---|---|
| 心跳间隔 | 5 秒 | 30 秒 |
| 服务剔除 | 15 秒超时,30 秒剔除 | 90 秒未收到心跳剔除 |
| 配置中心 | ✅ 内置支持 | ❌ 不支持 |
| 配置推送 | 服务变更时主动推送 | 客户端定时拉取(30 秒) |
| 一致性模式 | 支持 AP/CP 模式切换 | 仅 AP 模式(高可用) |
| 控制台 | 功能丰富的 Web 控制台 | 基础功能 |
| 维护状态 | 活跃开发中 | 已停止维护 |
部署模式
| 模式 | 适用场景 | 特点 |
|---|---|---|
| 单机模式 | 开发、测试环境 | 快速启动,使用内置 Derby 数据库 |
| 集群模式 | 生产环境 | 高可用,至少 3 个节点,外接 MySQL 持久化 |