-
[第三部分:Spring Cloud Alibaba技术体系](#第三部分:Spring Cloud Alibaba技术体系)
- [3.1 Spring Cloud Alibaba简介](#3.1 Spring Cloud Alibaba简介)
- [3.2 核心组件详解](#3.2 核心组件详解)
- [3.3 组件对比与选型](#3.3 组件对比与选型)
-
- [4.1 Dubbo:高性能RPC框架](#4.1 Dubbo:高性能RPC框架)
- [4.2 Nacos:动态服务发现与配置管理](#4.2 Nacos:动态服务发现与配置管理)
- [4.3 Sentinel:流量防护与服务降级](#4.3 Sentinel:流量防护与服务降级)
- [4.4 RocketMQ:分布式消息中间件](#4.4 RocketMQ:分布式消息中间件)
- [4.5 Seata:分布式事务解决方案](#4.5 Seata:分布式事务解决方案)
引言
微服务架构已经成为现代互联网应用的主流架构模式。从Netflix、Amazon等硅谷巨头,到阿里巴巴、腾讯等国内互联网公司,都在大规模实践微服务架构。
然而,微服务并非银弹。它在带来敏捷性、可扩展性、技术异构等优势的同时,也引入了分布式系统的复杂性、服务间通信开销、数据一致性等挑战。
本文将从理论到实践,系统地介绍微服务架构:
- 理论篇:微服务的定义、原则、分布式系统理论、设计模式
- 技术篇:Spring Cloud与Spring Cloud Alibaba技术栈详解
- 生态篇:阿里巴巴微服务生态(Dubbo、Nacos、Sentinel、RocketMQ、Seata)
第三部分:Spring Cloud Alibaba技术体系
3.1 Spring Cloud Alibaba简介
3.1.1 什么是Spring Cloud Alibaba?
Spring Cloud Alibaba是阿里巴巴结合自身微服务实践,开源的一套微服务解决方案,致力于提供微服务开发的一站式解决方案。
核心优势:
- 🚀 阿里巴巴实践验证:经过阿里巴巴双11等大促验证
- 🚀 中文文档友好:完善的中文文档和社区支持
- 🚀 功能强大:集成了服务注册、配置、限流、消息、分布式事务
- 🚀 性能优秀:相比Netflix组件,性能更好
- 🚀 持续维护:阿里巴巴团队持续维护更新
3.1.2 Spring Cloud Alibaba架构全景
存储层
Spring Cloud Alibaba组件
应用层
网关层
客户端层
Dubb
Dubb
Web/App/小程序
Spring Cloud Gateway
- Sentinel限流
订单服务
用户服务
商品服务
支付服务
Nacos
服务注册+配置中心
Sentinel
流量防护
RocketMQ
消息队列
Dubbo
RPC框架
Seata
分布式事务
MySQL
Redis
Elasticsearch
3.1.3 核心组件一览
| 组件 | 功能 | 替代组件 | 状态 |
|---|---|---|---|
| Nacos | 服务注册+配置中心 | Eureka + Config Server | ✅ 活跃 |
| Sentinel | 流量防护+熔断降级 | Hystrix | ✅ 活跃 |
| RocketMQ | 分布式消息队列 | RabbitMQ、Kafka | ✅ 活跃 |
| Dubbo | 高性能RPC框架 | Feign、gRPC | ✅ 活跃 |
| Seata | 分布式事务 | 无 | ✅ 活跃 |
| OSS | 阿里云对象存储 | MinIO、AWS S3 | ✅ 活跃 |
| SchedulerX | 分布式任务调度 | XXL-Job | ✅ 活跃 |
3.2 核心组件详解
3.2.1 Nacos - 动态服务发现与配置管理
Nacos = Naming + Configuration Service
Nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
核心功能:
Nacos核心功能
服务注册与发现
Service Discovery
动态配置管理
Configuration Management
动态DNS服务
Dynamic DNS
服务及元数据管理
Service Metadata Management
AP模式
最终一致性
CP模式
强一致性
配置动态刷新
配置版本管理
配置灰度发布
1. 服务注册与发现
支持两种模式:
| 模式 | CAP | 一致性协议 | 适用场景 |
|---|---|---|---|
| AP模式 | 可用性优先 | Distro协议 | 临时实例、高可用优先 |
| CP模式 | 一致性优先 | Raft协议 | 持久化实例、数据一致性优先 |
临时实例 vs 持久化实例:
| 特性 | 临时实例(默认) | 持久化实例 |
|---|---|---|
| 健康检查 | 客户端主动上报心跳 | 服务端主动探测 |
| 实例下线 | 心跳超时自动剔除 | 标记为不健康,不剔除 |
| 适用场景 | 微服务实例(动态扩缩容) | 数据库、缓存等基础设施 |
| CAP模式 | AP | CP |
Nacos服务注册流程:
服务消费者 Nacos Server 服务实例 服务消费者 Nacos Server 服务实例 心跳超时15秒,标记不健康 超时30秒,剔除实例 1. 服务注册 2. 存储实例信息 3. 心跳续约(每5秒) 4. 订阅服务 5. 推送服务列表 6. 服务变更推送(UDP) 7. 服务下线(主动) 8. 推送服务变更
Nacos vs Eureka对比:
| 特性 | Nacos | Eureka |
|---|---|---|
| CAP模型 | 支持AP和CP切换 | AP |
| 健康检查 | 支持TCP、HTTP、MySQL | 客户端心跳 |
| 负载均衡 | 支持权重配置 | 不支持 |
| 雪崩保护 | 支持(阈值保护) | 支持(自我保护机制) |
| 自动注销 | 支持 | 支持 |
| 监听支持 | 支持(长轮询+UDP推送) | 支持(轮询) |
| 多数据中心 | 支持 | ❌ |
| 跨注册中心 | 支持 | ❌ |
| 配置中心 | ✅ | ❌ |
| 社区活跃度 | 活跃(阿里) | 停止维护 |
2. 配置中心
为什么选择Nacos Config?
- ✅ 动态刷新:配置修改后实时生效,无需重启
- ✅ 版本管理:配置历史版本,一键回滚
- ✅ 灰度发布:配置灰度发布,逐步生效
- ✅ 权限管理:配置修改需要权限
- ✅ 多环境:开发、测试、生产环境隔离
- ✅ 多格式:支持properties、yaml、json、xml
Nacos配置模型:
Namespace(命名空间)- 用于隔离环境
├── dev(开发环境)
├── test(测试环境)
└── prod(生产环境)
├── Group(分组)- 用于隔离不同应用
│ ├── order-service
│ ├── user-service
│ └── product-service
└── Data ID(配置ID)- 具体配置文件
├── order-service-mysql.yaml
├── order-service-redis.yaml
└── order-service-mq.yaml
配置优先级:
远程配置 > 本地配置
shared-configs > extension-configs > 主配置
profile配置 > 默认配置
配置动态刷新:
使用@RefreshScope注解实现配置自动刷新:
java
@RestController
@RefreshScope // 配置刷新注解
public class ConfigController {
@Value("${app.config.message}")
private String message;
@GetMapping("/config")
public String getConfig() {
return message; // 配置修改后自动刷新
}
}
3.2.2 Sentinel - 流量防护卫士
Sentinel是什么?
Sentinel是面向分布式服务架构的流量控制组件,以流量为切入点,提供流量控制、熔断降级、系统负载保护等多个维度的稳定性保障。
核心功能:
Sentinel核心功能
流量控制
Flow Control
熔断降级
Circuit Breaking
系统负载保护
System Protection
热点参数限流
Hotspot Protection
集群流控
Cluster Flow Control
QPS限流
线程数限流
关联限流
链路限流
慢调用比例
异常比例
异常数
CPU使用率
内存使用率
系统负载
入口QPS
1. 流量控制
流控规则:
| 流控模式 | 说明 | 场景 |
|---|---|---|
| 直接 | 直接限流当前资源 | 保护当前接口 |
| 关联 | 关联资源达到阈值时,限流当前资源 | 读写分离、保护写操作 |
| 链路 | 只统计从指定链路访问的流量 | 细粒度流控 |
流控效果:
| 流控效果 | 说明 | 适用场景 |
|---|---|---|
| 快速失败 | 直接拒绝超出阈值的请求 | 严格流控 |
| Warm Up | 预热/冷启动方式,逐渐提升阈值 | 防止冷启动时瞬间压垮系统 |
| 排队等待 | 匀速排队,让请求匀速通过 | 脉冲流量削峰填谷 |
示例:
java
// QPS限流:每秒最多100个请求
@SentinelResource(value = "getOrder",
blockHandler = "handleBlock")
public Order getOrder(Long orderId) {
return orderService.getById(orderId);
}
// 降级方法
public Order handleBlock(Long orderId, BlockException ex) {
return Order.defaultOrder();
}
2. 熔断降级
熔断策略:
| 策略 | 触发条件 | 说明 |
|---|---|---|
| 慢调用比例 | 慢调用比例 > 阈值 | RT > 最大响应时间的请求占比 |
| 异常比例 | 异常比例 > 阈值 | 异常请求占比 |
| 异常数 | 异常数 > 阈值 | 异常请求数量 |
熔断状态转换:
初始状态
触发熔断条件
熔断时长过后
探测成功
探测失败
关闭状态
正常处理请求
打开状态
熔断,快速失败
半开状态
探测恢复
3. 系统负载保护
当系统负载较高时,自动拒绝请求,保护系统稳定:
| 指标 | 阈值 | 说明 |
|---|---|---|
| CPU使用率 | > 80% | CPU使用率过高时拒绝请求 |
| 系统负载 | > 系统核心数 × 2.5 | Load过高时拒绝请求 |
| 平均RT | > 阈值 | 响应时间过长时拒绝请求 |
| 并发线程数 | > 阈值 | 线程数过多时拒绝请求 |
| 入口QPS | > 阈值 | 总体QPS过高时拒绝请求 |
4. 实时监控与控制台
Sentinel Dashboard提供了强大的实时监控和规则配置功能:
- 📊 实时监控:QPS、RT、通过QPS、拒绝QPS
- 📊 机器列表:查看所有接入Sentinel的机器
- 📊 规则管理:流控规则、降级规则、热点规则、系统规则
- 📊 集群流控:配置集群流控规则
- 📊 规则推送:动态推送规则到应用
Sentinel vs Hystrix对比:
| 特性 | Sentinel | Hystrix |
|---|---|---|
| 状态 | 活跃(阿里) | 停止维护 |
| 隔离策略 | 信号量隔离 | 线程池隔离、信号量隔离 |
| 熔断降级 | 慢调用比例、异常比例、异常数 | 基于异常比例 |
| 实时监控 | ✅ 强大的Dashboard | 基础Dashboard |
| 规则配置 | 动态配置、推送 | 代码配置 |
| 流量控制 | ✅ 多种流控模式 | ❌ |
| 系统负载保护 | ✅ | ❌ |
| 热点限流 | ✅ | ❌ |
| 集群流控 | ✅ | ❌ |
| 规则持久化 | 支持多种方式(文件、Nacos、Apollo) | ❌ |
| 性能 | 优秀(吞吐量高,延迟低) | 一般(线程池隔离开销大) |
为什么选择Sentinel?
- ✅ 功能更强大:流控、降级、系统保护、热点限流
- ✅ 性能更好:吞吐量更高,延迟更低
- ✅ 实时监控:Dashboard可视化监控
- ✅ 动态规则:规则可以动态推送,无需重启
- ✅ 持续维护:阿里巴巴持续维护
3.3 组件对比与选型
3.3.1 Spring Cloud vs Spring Cloud Alibaba
全面对比:
| 功能 | Spring Cloud | Spring Cloud Alibaba | 推荐 |
|---|---|---|---|
| 服务注册 | Eureka(停止维护) | Nacos | ⭐️⭐️⭐️⭐️⭐️ Nacos |
| 配置中心 | Config Server | Nacos Config | ⭐️⭐️⭐️⭐️⭐️ Nacos Config |
| 负载均衡 | Ribbon(已移除)→ LoadBalancer | Ribbon + Dubbo | ⭐️⭐️⭐️⭐️ LoadBalancer |
| 服务调用 | OpenFeign | Dubbo | ⭐️⭐️⭐️⭐️ OpenFeign(HTTP) ⭐️⭐️⭐️⭐️⭐️ Dubbo(RPC) |
| 熔断降级 | Hystrix(已移除)→ Resilience4j | Sentinel | ⭐️⭐️⭐️⭐️⭐️ Sentinel |
| API网关 | Gateway | Gateway(通用) | ⭐️⭐️⭐️⭐️⭐️ Gateway |
| 链路追踪 | Sleuth + Zipkin | SkyWalking | ⭐️⭐️⭐️⭐️⭐️ SkyWalking |
| 消息队列 | Spring Cloud Stream | RocketMQ | ⭐️⭐️⭐️⭐️⭐️ RocketMQ |
| 分布式事务 | ❌ | Seata | ⭐️⭐️⭐️⭐️⭐️ Seata |
| 任务调度 | ❌ | SchedulerX、XXL-Job | ⭐️⭐️⭐️⭐️ XXL-Job |
3.3.2 技术选型决策树
Netflix全家桶
新项目
国内团队
国际团队
开始选型
已有技术栈?
逐步迁移到
Spring Cloud Alibaba
团队背景?
推荐:Spring Cloud Alibaba
Spring Cloud + 部分Alibaba组件
技术选型
Nacos: 注册+配置
Sentinel: 流控+降级
Dubbo: RPC调用
RocketMQ: 消息队列
Seata: 分布式事务
Gateway: API网关
SkyWalking: 链路追踪
选型理由:
| 组件 | 选型 | 理由 |
|---|---|---|
| Nacos | ⭐️⭐️⭐️⭐️⭐️ | 服务注册+配置中心二合一,阿里维护,中文文档友好 |
| Sentinel | ⭐️⭐️⭐️⭐️⭐️ | 功能强大,实时监控,阿里巴巴双11验证 |
| Dubbo | ⭐️⭐️⭐️⭐️⭐️ | 高性能RPC,核心服务间调用性能提升3-5倍 |
| RocketMQ | ⭐️⭐️⭐️⭐️⭐️ | 事务消息,延时消息,顺序消息,功能完善 |
| Seata | ⭐️⭐️⭐️⭐️ | 分布式事务,支持AT、TCC、SAGA多种模式 |
| Gateway | ⭐️⭐️⭐️⭐️⭐️ | 高性能,WebFlux非阻塞,官方推荐 |
| SkyWalking | ⭐️⭐️⭐️⭐️⭐️ | 无侵入,APM全方位监控,国产开源 |
3.3.4 混合使用方案
推荐组合:Spring Cloud + Spring Cloud Alibaba
Apache生态
Spring Cloud Alibaba组件
Spring Cloud组件
Spring Cloud Gateway
API网关
Spring Cloud LoadBalancer
负载均衡
OpenFeign
HTTP调用
Nacos
注册+配置
Sentinel
流控+降级
Dubbo
RPC调用
RocketMQ
消息队列
Seata
分布式事务
SkyWalking
链路追踪
为什么混合使用?
- Gateway:Spring Cloud官方推荐,高性能,文档完善
- Nacos:阿里出品,服务注册+配置中心,一站式解决方案
- Sentinel:阿里出品,功能强大,实时监控
- OpenFeign:HTTP调用简单,适合跨语言
- Dubbo:核心服务间RPC调用,性能更好
- SkyWalking:Apache顶级项目,无侵入,全方位监控
小结
第三部分介绍了Spring Cloud Alibaba技术体系:
- ✅ Spring Cloud Alibaba简介:阿里巴巴微服务解决方案,双11验证
- ✅ Nacos详解 :
- 服务注册与发现(支持AP/CP双模式)
- 动态配置中心(实时刷新、版本管理、灰度发布)
- 临时实例 vs 持久化实例
- ✅ Sentinel详解 :
- 流量控制(QPS限流、关联限流、链路限流)
- 熔断降级(慢调用、异常比例、异常数)
- 系统负载保护(CPU、内存、负载)
- 实时监控Dashboard
- ✅ 组件对比:Spring Cloud vs Spring Cloud Alibaba 全面对比
关键结论:
现代微服务架构推荐方案:
- 🌟 服务注册+配置:Nacos(一站式解决方案)
- 🌟 流量防护:Sentinel(功能强大,实时监控)
- 🌟 API网关:Spring Cloud Gateway(高性能,官方推荐)
- 🌟 服务调用:OpenFeign(HTTP)+ Dubbo(RPC)
- 🌟 消息队列:RocketMQ(事务消息,延时消息)
- 🌟 链路追踪:SkyWalking(无侵入,全方位监控)
- 🌟 分布式事务:Seata(AT、TCC、SAGA多种模式)
Spring Cloud Alibaba的核心优势:
- ✅ 阿里巴巴实践验证:经过双11等大促验证,稳定性有保障
- ✅ 中文文档友好:国内团队使用方便
- ✅ 功能更强大:相比Netflix组件,功能更丰富
- ✅ 性能更优秀:经过高并发场景优化
- ✅ 持续维护:阿里巴巴持续投入维护
第四部分:阿里巴巴微服务生态
4.1 Dubbo:高性能RPC框架
4.1.1 什么是Dubbo?
Apache Dubbo是阿里巴巴开源的高性能、轻量级的Java RPC框架,已成为Apache顶级项目。
核心优势:
- 🚀 高性能: 基于Netty NIO,单机QPS可达10万+
- 🚀 服务治理: 负载均衡、集群容错、服务降级、流量控制
- 🚀 多协议支持: Dubbo、HTTP、gRPC、Thrift、REST
- 🚀 注册中心: 支持Zookeeper、Nacos、Consul、Etcd
- 🚀 监控运维: Admin控制台、监控中心、链路追踪
4.1.2 Dubbo架构
Dubbo架构
- 服务注册 2. 服务订阅 3. 服务列表推送 4. RPC调用 5. 统计信息 5. 统计信息 管理
服务提供者
Provider
注册中心
Registry
Nacos/Zookeeper
服务消费者
Consumer
监控中心
Monitor
管理控制台
Dubbo Admin
工作流程:
- 服务注册: Provider启动时向Registry注册服务
- 服务订阅: Consumer启动时向Registry订阅所需服务
- 服务推送: Registry将Provider列表推送给Consumer
- RPC调用: Consumer基于负载均衡算法选择Provider发起调用
- 监控统计: Consumer和Provider定时发送统计数据到Monitor
4.1.3 Dubbo vs HTTP vs gRPC
| 特性 | Dubbo | HTTP REST | gRPC | RMI |
|---|---|---|---|---|
| 协议 | Dubbo私有协议 | HTTP/1.1 | HTTP/2 | Java RMI |
| 序列化 | Hessian/Protobuf/Kryo | JSON/XML | Protobuf | Java序列化 |
| 性能 | 优秀 (10万QPS) | 一般 (2万QPS) | 优秀 (8万QPS) | 一般 |
| 跨语言 | ❌ Java主导 | ✅ 完全支持 | ✅ 完全支持 | ❌ Java Only |
| 服务治理 | ✅ 完善 | ❌ 需自己实现 | ⚠️ 基础支持 | ❌ 无 |
| 负载均衡 | ✅ 客户端负载均衡 | 需Nginx/LVS | ⚠️ 基础支持 | ❌ 无 |
| 服务发现 | ✅ 内置 | ❌ 需集成 | ⚠️ 需集成 | ❌ 无 |
| 学习成本 | 中等 | 低 | 中等 | 低 |
| 适用场景 | Java微服务内部调用 | 对外API、跨语言 | 高性能跨语言调用 | 传统Java应用 |
4.1.4 Dubbo服务治理
1. 负载均衡策略
| 策略 | 说明 | 适用场景 |
|---|---|---|
| Random | 随机 (默认) | 服务性能相近 |
| RoundRobin | 轮询 | 服务性能相近,平均分配 |
| LeastActive | 最少活跃调用数 | 服务性能差异大,优先分配给性能好的 |
| ConsistentHash | 一致性Hash | 需要会话保持 (如购物车) |
| ShortestResponse | 最短响应时间 | 优先选择响应最快的 |
配置示例:
java
@DubboReference(
version = "1.0.0",
timeout = 3000,
retries = 2,
loadbalance = "leastactive", // 最少活跃调用数
cluster = "failover", // 失败自动切换
mock = "com.mythos.order.api.fallback.OrderServiceMock"
)
private OrderService orderService;
2. 集群容错策略
| 策略 | 说明 | 适用场景 |
|---|---|---|
| Failover | 失败自动切换 (默认) | 读操作、幂等写操作 |
| Failfast | 快速失败 | 非幂等写操作 (如新增订单) |
| Failsafe | 失败安全,忽略异常 | 日志记录、监控上报 |
| Failback | 失败自动恢复 | 消息通知 |
| Forking | 并行调用多个,一个成功即返回 | 实时性要求高的读操作 |
| Broadcast | 广播调用所有Provider | 缓存刷新 |
3. 服务降级
java
// 服务Mock降级
public class OrderServiceMock implements OrderService {
@Override
public OrderDTO getOrderById(Long orderId) {
// 降级逻辑: 返回默认订单或缓存数据
return OrderDTO.builder()
.orderId(orderId)
.orderStatus("UNKNOWN")
.message("服务暂时不可用,请稍后重试")
.build();
}
}
4.1.5 Dubbo配置示例
Provider配置:
yaml
dubbo:
application:
name: mythos-order-service
protocol:
name: dubbo
port: 20880
serialization: hessian2
registry:
address: nacos://localhost:8848
provider:
timeout: 3000
retries: 0
loadbalance: random
Consumer配置:
yaml
dubbo:
application:
name: mythos-user-service
registry:
address: nacos://localhost:8848
consumer:
timeout: 3000
retries: 2
check: false # 启动时不检查Provider是否可用
性能对比:
测试场景: 1000并发,10万次调用
- Dubbo: QPS = 100,000, RT = 10ms
- OpenFeign: QPS = 20,000, RT = 50ms
- gRPC: QPS = 80,000, RT = 12ms
Dubbo性能提升: 3-5倍
4.2 Nacos:动态服务发现与配置管理
4.2.1 Nacos核心功能
Nacos = Na ming + Co nfiguration Service
Nacos核心功能
服务注册与发现
Service Discovery
动态配置管理
Configuration Management
动态DNS服务
Dynamic DNS
服务元数据管理
Service Metadata
AP模式
最终一致性
Distro协议
CP模式
强一致性
Raft协议
配置动态刷新
实时生效
配置版本管理
一键回滚
配置灰度发布
逐步生效
4.2.2 服务注册与发现 (深度解析)
AP模式 vs CP模式
| 特性 | AP模式 (默认) | CP模式 |
|---|---|---|
| 一致性协议 | Distro协议 (最终一致性) | Raft协议 (强一致性) |
| 实例类型 | 临时实例 (Ephemeral) | 持久化实例 (Persistent) |
| 健康检查 | 客户端主动上报心跳 | 服务端主动探测 (HTTP/TCP) |
| 实例下线 | 心跳超时自动剔除 | 标记为不健康,不剔除 |
| CAP权衡 | 可用性优先 (A) | 一致性优先 © |
| 适用场景 | 微服务实例 (动态扩缩容) | 数据库、缓存等基础设施 |
| 网络分区 | 各节点独立服务 | 选举新Leader |
临时实例 vs 持久化实例
服务消费者 Nacos Server 服务实例 服务消费者 Nacos Server 服务实例 临时实例 (AP模式) 超时15秒标记不健康 超时30秒自动剔除 持久化实例 (CP模式) 探测失败标记不健康 但不剔除实例 1. 服务注册 (ephemeral=true) 2. 存储到内存 3. 心跳续约 (每5秒) 4. 服务注册 (ephemeral=false) 5. 持久化到数据库 (Raft同步) 6. 健康检查 (HTTP探测)
服务注册流程详解:
java
// 临时实例注册 (默认)
@SpringBootApplication
@EnableDiscoveryClient
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
// application.yml
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
namespace: dev
group: DEFAULT_GROUP
ephemeral: true # 临时实例 (AP模式)
heart-beat-interval: 5000 # 心跳间隔 5秒
heart-beat-timeout: 15000 # 心跳超时 15秒
ip-delete-timeout: 30000 # 实例删除超时 30秒
工作机制:
- 服务注册: 服务启动时向Nacos注册,携带IP、端口、元数据
- 心跳续约: 客户端每5秒发送一次心跳 (临时实例)
- 健康检查 :
- 临时实例: 15秒未收到心跳→不健康,30秒→剔除
- 持久化实例: Server主动探测→标记不健康但不剔除
- 服务发现: Consumer订阅服务,Nacos推送Provider列表 (UDP推送 + 定时轮询)
- 服务下线: 主动调用注销接口 或 心跳超时自动剔除
Distro协议 (AP模式):
- 每个Nacos节点负责一部分服务实例 (通过Hash分片)
- 节点间通过Gossip协议同步数据
- 最终一致性,允许短暂数据不一致
- 网络分区时各节点独立服务,分区恢复后自动同步
Raft协议 (CP模式):
- Leader选举机制,所有写操作经过Leader
- Leader将数据同步到多数Follower后返回成功
- 强一致性,保证数据不丢失
- 网络分区时少数节点不可用
4.2.3 配置管理 (深度解析)
配置模型:
Namespace (命名空间) - 环境隔离
├── dev (开发环境)
├── test (测试环境)
└── prod (生产环境)
└── Group (分组) - 应用隔离
├── order-service
├── user-service
└── product-service
└── Data ID (配置文件)
├── application.yml # 主配置
├── application-mysql.yml # MySQL配置
├── application-redis.yml # Redis配置
└── application-mq.yml # MQ配置
配置优先级:
本地配置 < 远程配置
默认配置 < profile配置
主配置 < extension-configs < shared-configs
配置加载顺序:
yaml
spring:
application:
name: order-service
profiles:
active: dev
cloud:
nacos:
config:
server-addr: localhost:8848
namespace: dev
group: DEFAULT_GROUP
file-extension: yml
# 主配置: order-service-dev.yml
# 扩展配置 (优先级最高)
extension-configs:
- data-id: order-service-mysql.yml
group: DEFAULT_GROUP
refresh: true
- data-id: order-service-redis.yml
group: DEFAULT_GROUP
refresh: true
# 共享配置 (多个服务共享)
shared-configs:
- data-id: common-config.yml
group: DEFAULT_GROUP
refresh: true
加载顺序 (后加载的覆盖先加载的):
- shared-configs (共享配置)
- extension-configs (扩展配置)
- order-service.yml (主配置,不带profile)
- order-service-dev.yml (主配置,带profile) - 优先级最高
动态配置刷新:
java
@RestController
@RefreshScope // 配置刷新注解
public class ConfigController {
@Value("${app.config.message}")
private String message;
@Value("${app.config.timeout:3000}")
private Integer timeout;
@GetMapping("/config")
public Map<String, Object> getConfig() {
return Map.of(
"message", message, // 配置修改后自动刷新
"timeout", timeout
);
}
}
// 配置监听器 (高级用法)
@Component
public class ConfigListener {
@NacosConfigListener(dataId = "order-service-dev.yml", groupId = "DEFAULT_GROUP")
public void onConfigChange(String newContent) {
log.info("配置发生变更: {}", newContent);
// 自定义刷新逻辑
}
}
配置灰度发布:
是
否
- 创建配置 2. 配置灰度发布 3. 选择灰度策略 按IP灰度
192.168.1.10
按比例灰度
10%流量
4. 发布灰度配置 5. 验证灰度实例 6. 验证通过? 7. 全量发布 8. 回滚配置 完成
灰度发布示例:
- 在Nacos控制台创建配置
- 点击"灰度发布"
- 选择灰度规则 (IP/百分比)
- 灰度实例先加载新配置,验证
- 验证通过后全量发布,失败则回滚
配置版本管理与回滚:
Nacos自动保存配置历史版本 (最多保留30个版本),支持一键回滚:
- 进入配置详情页
- 点击"历史版本"
- 选择目标版本
- 点击"回滚"
4.3 Sentinel:流量防护与服务降级
4.3.1 Sentinel核心功能
Sentinel核心功能
流量控制
Flow Control
熔断降级
Circuit Breaking
系统负载保护
System Protection
热点参数限流
Hotspot Protection
集群流控
Cluster Flow Control
QPS限流
每秒请求数限制
并发线程数限流
并发控制
关联限流
关联资源限流
链路限流
调用链路限流
慢调用比例
RT超时熔断
异常比例
错误率熔断
异常数
异常次数熔断
CPU使用率
CPU > 80%拒绝
系统负载
Load过高拒绝
平均RT
响应时间过长
入口QPS
总QPS过高
4.3.2 流量控制
流量控制规则:
| 限流模式 | 说明 | 场景 |
|---|---|---|
| 直接 | 直接限流当前资源 | 保护当前接口,如 QPS > 100 拒绝 |
| 关联 | 关联资源达到阈值时,限流当前资源 | 读写分离: 写操作QPS高时,限制读操作 |
| 链路 | 只统计从指定链路访问的流量 | 细粒度流控: 只限制从A入口进入的流量 |
流控效果:
| 流控效果 | 说明 | 适用场景 |
|---|---|---|
| 快速失败 | 直接拒绝超出阈值的请求 | 严格流控,直接返回 429 |
| Warm Up | 预热/冷启动,逐渐提升阈值 | 防止冷启动时瞬间压垮系统 (如缓存预热) |
| 排队等待 | 匀速排队,让请求匀速通过 | 脉冲流量削峰填谷 (秒杀场景) |
代码示例:
java
@RestController
public class OrderController {
// QPS限流: 每秒最多100个请求
@SentinelResource(value = "getOrder",
blockHandler = "handleBlock",
fallback = "handleFallback")
@GetMapping("/orders/{orderId}")
public Response<OrderDTO> getOrder(@PathVariable Long orderId) {
return Response.success(orderService.getById(orderId));
}
// 降级方法: 限流时调用
public Response<OrderDTO> handleBlock(Long orderId, BlockException ex) {
log.warn("订单查询被限流, orderId={}", orderId);
return Response.fail("系统繁忙,请稍后重试");
}
// 兜底方法: 业务异常时调用
public Response<OrderDTO> handleFallback(Long orderId, Throwable ex) {
log.error("订单查询失败, orderId={}", orderId, ex);
return Response.fail("订单查询失败");
}
}
Sentinel规则配置 (通过Nacos持久化):
java
@Configuration
public class SentinelConfig {
@PostConstruct
public void initRules() {
// 流控规则
List<FlowRule> flowRules = new ArrayList<>();
FlowRule rule = new FlowRule("getOrder");
rule.setCount(100); // QPS阈值 100
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setLimitApp("default");
rule.setStrategy(RuleConstant.STRATEGY_DIRECT);
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
flowRules.add(rule);
FlowRuleManager.loadRules(flowRules);
}
}
4.3.3 熔断降级
熔断策略:
| 策略 | 触发条件 | 说明 |
|---|---|---|
| 慢调用比例 | RT > 最大响应时间的请求占比 > 阈值 | 例如: RT > 1000ms的请求占比 > 50% |
| 异常比例 | 异常请求占比 > 阈值 | 例如: 异常请求占比 > 50% |
| 异常数 | 异常请求数 > 阈值 | 例如: 1分钟内异常数 > 10次 |
熔断器状态机:
初始状态
触发熔断条件
(慢调用比例/异常比例/异常数)
熔断时长过后
(默认5秒)
探测成功
(请求正常)
探测失败
(请求异常)
关闭状态
正常处理请求
统计慢调用/异常
打开状态
熔断,快速失败
不调用服务
半开状态
探测恢复
允许少量请求通过
熔断规则配置:
java
// 慢调用比例熔断
DegradeRule slowCallRule = new DegradeRule("getOrder")
.setGrade(RuleConstant.DEGRADE_GRADE_RT)
.setCount(1000) // 最大RT: 1000ms
.setSlowRatioThreshold(0.5) // 慢调用比例阈值: 50%
.setMinRequestAmount(10) // 最小请求数: 10
.setStatIntervalMs(10000) // 统计时长: 10秒
.setTimeWindow(5); // 熔断时长: 5秒
// 异常比例熔断
DegradeRule exceptionRatioRule = new DegradeRule("createOrder")
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
.setCount(0.5) // 异常比例阈值: 50%
.setMinRequestAmount(10)
.setStatIntervalMs(10000)
.setTimeWindow(10); // 熔断时长: 10秒
// 异常数熔断
DegradeRule exceptionCountRule = new DegradeRule("payOrder")
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT)
.setCount(10) // 异常数阈值: 10次
.setStatIntervalMs(60000) // 统计时长: 1分钟
.setTimeWindow(10);
4.3.4 系统负载保护
当系统负载较高时,自动拒绝请求,保护系统稳定:
| 指标 | 阈值 | 说明 |
|---|---|---|
| CPU使用率 | > 80% | CPU使用率过高时拒绝请求 |
| 系统负载 | > 系统核心数 × 2.5 | Load过高时拒绝请求 (仅Linux) |
| 平均RT | > 阈值 (ms) | 响应时间过长时拒绝请求 |
| 并发线程数 | > 阈值 | 线程数过多时拒绝请求 |
| 入口QPS | > 阈值 | 总体QPS过高时拒绝请求 |
系统保护规则:
java
SystemRule systemRule = new SystemRule();
systemRule.setHighestCpuUsage(0.8); // CPU > 80%
systemRule.setHighestSystemLoad(10.0); // Load > 10 (4核 × 2.5)
systemRule.setAvgRt(1000); // 平均RT > 1000ms
systemRule.setMaxThread(100); // 并发线程数 > 100
systemRule.setQps(10000); // 入口QPS > 10000
SystemRuleManager.loadRules(Collections.singletonList(systemRule));
4.3.5 Sentinel Dashboard
实时监控功能:
- 📊 实时QPS、RT、通过QPS、拒绝QPS
- 📊 机器列表: 查看所有接入Sentinel的应用
- 📊 规则管理: 流控规则、降级规则、热点规则、系统规则
- 📊 集群流控: 配置集群流控规则
- 📊 规则推送: 动态推送规则到应用
规则持久化到Nacos:
yaml
# application.yml
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080 # Sentinel Dashboard地址
datasource:
flow: # 流控规则
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-flow-rules
groupId: SENTINEL_GROUP
rule-type: flow
degrade: # 降级规则
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-degrade-rules
groupId: SENTINEL_GROUP
rule-type: degrade
Sentinel vs Hystrix对比:
| 特性 | Sentinel | Hystrix |
|---|---|---|
| 状态 | ✅ 活跃 (阿里) | ❌ 停止维护 |
| 隔离策略 | 信号量隔离 | 线程池隔离、信号量隔离 |
| 熔断降级 | 慢调用比例、异常比例、异常数 | 基于异常比例 |
| 实时监控 | ✅ 强大的Dashboard | 基础Dashboard |
| 规则配置 | 动态配置、推送 | 代码配置 |
| 流量控制 | ✅ 多种流控模式 | ❌ 无 |
| 系统负载保护 | ✅ CPU、Load、RT | ❌ 无 |
| 热点限流 | ✅ 参数级限流 | ❌ 无 |
| 集群流控 | ✅ Token Server模式 | ❌ 无 |
| 规则持久化 | 支持 (Nacos/Apollo/ZK) | ❌ 无 |
| 性能 | 优秀 (吞吐量高,延迟低) | 一般 (线程池开销大) |
4.4 RocketMQ:分布式消息中间件
4.4.1 RocketMQ架构
RocketMQ架构
- 获取路由 2. 返回Broker列表 3. 发送消息 4. 同步复制 5. 同步ACK 6. 发送ACK 7. 订阅Topic 8. 返回Broker列表 9. 拉取消息 10. 返回消息 11. 消费ACK Producer
生产者
NameServer
命名服务
Broker Master
主节点
Broker Slave
从节点
Consumer
消费者
核心组件:
- NameServer: 轻量级注册中心,管理Broker路由信息,无状态集群
- Broker: 消息存储和转发,支持主从部署
- Producer: 消息生产者,负载均衡发送消息
- Consumer: 消息消费者,支持集群消费和广播消费
4.4.2 消息类型
| 消息类型 | 说明 | 适用场景 |
|---|---|---|
| 普通消息 | 普通的异步消息 | 日志收集、异步通知 |
| 顺序消息 | 保证FIFO顺序 | 订单状态流转、Binlog同步 |
| 事务消息 | 分布式事务,支持Half Message | 订单支付、库存扣减 |
| 延时消息 | 延迟消费,18个固定延迟级别 | 订单超时关闭、定时任务 |
| 批量消息 | 批量发送,提高吞吐量 | 批量数据同步 |
延时消息级别:
java
// 18个延迟级别 (1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h)
message.setDelayTimeLevel(3); // 10秒后消费
4.4.3 事务消息
事务消息工作流程:
本地数据库 Consumer Broker Producer 本地数据库 Consumer Broker Producer alt [本地事务成功] [本地事务失败] Broker回查本地事务状态 1. 发送Half Message (半消息) 2. 存储Half Message 3. Half Message发送成功 4. 执行本地事务 (创建订单) 5a. Commit (提交消息) 6a. Half Message → Normal Message 7a. 消费者消费消息 5b. Rollback (回滚消息) 6b. 删除Half Message 8. 回查事务状态 (如果长时间未收到Commit/Rollback) 9. 查询订单是否创建 10. 返回事务状态 (Commit/Rollback)
代码示例:
java
@Service
public class OrderTransactionService {
@Autowired
private RocketMQTemplate rocketMQTemplate;
@Autowired
private OrderService orderService;
/**
* 发送事务消息: 创建订单 + 扣减库存
*/
public void createOrderWithTransaction(OrderDTO orderDTO) {
// 发送事务消息
Message<OrderDTO> message = MessageBuilder
.withPayload(orderDTO)
.build();
rocketMQTemplate.sendMessageInTransaction(
"order-topic",
message,
orderDTO // arg参数传递给executeLocalTransaction
);
}
/**
* 事务监听器
*/
@RocketMQTransactionListener
static class OrderTransactionListener implements RocketMQLocalTransactionListener {
@Autowired
private OrderService orderService;
/**
* 执行本地事务
*/
@Override
public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
try {
OrderDTO orderDTO = (OrderDTO) arg;
// 1. 创建订单 (本地事务)
orderService.createOrder(orderDTO);
// 2. 本地事务成功 → Commit消息
log.info("本地事务执行成功, 提交消息");
return RocketMQLocalTransactionState.COMMIT;
} catch (Exception e) {
// 3. 本地事务失败 → Rollback消息
log.error("本地事务执行失败, 回滚消息", e);
return RocketMQLocalTransactionState.ROLLBACK;
}
}
/**
* Broker回查本地事务状态
*/
@Override
public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
try {
// 从消息中提取订单ID
OrderDTO orderDTO = JSON.parseObject(
new String((byte[]) msg.getPayload()),
OrderDTO.class
);
// 查询订单是否创建成功
Order order = orderService.getByOrderNo(orderDTO.getOrderNo());
if (order != null) {
log.info("回查本地事务: 订单已创建, 提交消息");
return RocketMQLocalTransactionState.COMMIT;
} else {
log.warn("回查本地事务: 订单不存在, 回滚消息");
return RocketMQLocalTransactionState.ROLLBACK;
}
} catch (Exception e) {
log.error("回查本地事务异常", e);
return RocketMQLocalTransactionState.ROLLBACK;
}
}
}
}
/**
* 消费者: 扣减库存
*/
@Service
@RocketMQMessageListener(
topic = "order-topic",
consumerGroup = "inventory-consumer-group"
)
public class InventoryConsumer implements RocketMQListener<OrderDTO> {
@Autowired
private InventoryService inventoryService;
@Override
public void onMessage(OrderDTO orderDTO) {
log.info("收到订单创建消息, 扣减库存: {}", orderDTO);
// 扣减库存
inventoryService.deduct(orderDTO.getSkuId(), orderDTO.getQuantity());
}
}
事务消息关键点:
- Half Message: 消息发送到Broker但对Consumer不可见
- 本地事务: Producer执行本地事务 (如创建订单)
- Commit/Rollback: 本地事务成功→Commit,失败→Rollback
- 事务回查: Broker定时回查Producer的事务状态 (默认15次,每次间隔60秒)
4.4.4 消费模式
集群消费 vs 广播消费:
| 消费模式 | 说明 | 适用场景 |
|---|---|---|
| 集群消费 (Clustering) | 一条消息只会被Consumer Group中的一个实例消费 | 订单处理、库存扣减 (默认模式) |
| 广播消费 (Broadcasting) | 一条消息会被Consumer Group中的所有实例消费 | 缓存刷新、配置更新 |
java
// 集群消费 (默认)
@RocketMQMessageListener(
topic = "order-topic",
consumerGroup = "order-consumer-group",
messageModel = MessageModel.CLUSTERING // 集群消费
)
public class OrderConsumer implements RocketMQListener<OrderDTO> {
// 一条消息只会被一个实例消费
}
// 广播消费
@RocketMQMessageListener(
topic = "cache-refresh-topic",
consumerGroup = "cache-consumer-group",
messageModel = MessageModel.BROADCASTING // 广播消费
)
public class CacheRefreshConsumer implements RocketMQListener<String> {
// 一条消息会被所有实例消费 (如3个实例都收到)
}
4.4.5 RocketMQ vs Kafka vs RabbitMQ
| 特性 | RocketMQ | Kafka | RabbitMQ |
|---|---|---|---|
| 开发语言 | Java | Scala | Erlang |
| 性能 | 10万+ QPS | 100万+ QPS | 万级 QPS |
| 时效性 | ms级 | ms级 | us级 |
| 可用性 | 高 (主从架构) | 高 (分布式架构) | 高 (镜像队列) |
| 事务消息 | ✅ 完善 | ❌ 无 | ❌ 无 |
| 延时消息 | ✅ 18个固定级别 | ❌ 无 | ✅ 插件支持 |
| 顺序消息 | ✅ 全局顺序/分区顺序 | ✅ 分区顺序 | ❌ 弱支持 |
| 消息回溯 | ✅ 按时间/Offset | ✅ 按Offset | ❌ 无 |
| 消息堆积 | ✅ 亿级 (磁盘存储) | ✅ 亿级 | ⚠️ 内存受限 |
| 消息过滤 | ✅ Tag、SQL92 | ❌ 无 | ❌ 无 |
| 适用场景 | 业务消息、事务消息、顺序消息 | 日志收集、大数据实时计算 | 低延时、复杂路由 |
4.5 Seata:分布式事务解决方案
4.5.1 Seata架构
Seata分布式事务架构
- 开启全局事务 2. 返回XID 3. 注册分支事务 4. 分支注册 5. 执行业务SQL 6. 提交分支事务 7. 调用库存服务 8. 分支注册 9. 执行业务SQL 10. 提交分支事务 11. 调用账户服务 12. 分支注册 13. 执行业务SQL 14. 提交分支事务 15. 提交/回滚全局事务 16. 通知各RM提交/回滚 16. 通知各RM提交/回滚 16. 通知各RM提交/回滚 TM
Transaction Manager
事务管理器
TC
Transaction Coordinator
事务协调器
Seata Server
RM
Resource Manager
订单服务
RM
Resource Manager
库存服务
RM
Resource Manager
账户服务
三大角色:
- TC (Transaction Coordinator): 事务协调器,维护全局事务和分支事务状态,驱动全局提交或回滚
- TM (Transaction Manager): 事务管理器,定义全局事务范围,开启/提交/回滚全局事务
- RM (Resource Manager): 资源管理器,管理分支事务,与TC交互注册分支和报告分支状态
4.5.2 Seata四大事务模式
| 模式 | 说明 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| AT模式 | 自动模式,无代码侵入,基于undo_log回滚 | 简单易用,无代码改动 | 性能一般,依赖数据库 | 大部分业务场景 |
| TCC模式 | Try-Confirm-Cancel,手动补偿 | 性能好,无锁 | 代码侵入性强 | 订单、支付等核心业务 |
| SAGA模式 | 长事务,事件驱动,正向+补偿 | 适合长流程 | 编程复杂 | 订单履约、退款流程 |
| XA模式 | 传统XA协议,强一致性 | 强一致性 | 性能差,锁定时间长 | 金融场景 |
4.5.3 AT模式详解
AT模式原理:
- 一阶段: 执行业务SQL,生成undo_log (前后镜像),提交本地事务
- 二阶段 :
- 提交: 异步删除undo_log
- 回滚: 根据undo_log自动反向补偿
undo_log表结构:
sql
CREATE TABLE `undo_log` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`branch_id` BIGINT NOT NULL COMMENT '分支事务ID',
`xid` VARCHAR(100) NOT NULL COMMENT '全局事务ID',
`context` VARCHAR(128) NOT NULL COMMENT '上下文',
`rollback_info` LONGBLOB NOT NULL COMMENT '回滚信息(前后镜像)',
`log_status` INT NOT NULL COMMENT '日志状态: 0-正常, 1-已回滚',
`log_created` DATETIME NOT NULL COMMENT '创建时间',
`log_modified` DATETIME NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Seata AT模式undo日志表';
AT模式工作流程:
账户服务 (RM) 库存服务 (RM) 订单服务 (RM) Seata Server (TC) 订单服务 (TM) 账户服务 (RM) 库存服务 (RM) 订单服务 (RM) Seata Server (TC) 订单服务 (TM) 1. 开启全局事务 2. 返回XID=123 3. 创建订单 4. 生成undo_log (前镜像) 5. 执行INSERT订单 6. 生成undo_log (后镜像) 7. 注册分支事务 branchId=1001 8. 提交本地事务 9. 扣减库存 10. 生成undo_log 11. 执行UPDATE库存-10 12. 注册分支事务 branchId=1002 13. 提交本地事务 14. 扣减余额 15. 生成undo_log 16. 执行UPDATE余额-100 17. 注册分支事务 branchId=1003 18. 提交本地事务 19. 提交全局事务 XID=123 20. 删除undo_log 20. 删除undo_log 20. 删除undo_log
代码示例:
java
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private InventoryClient inventoryClient; // Feign调用库存服务
@Autowired
private AccountClient accountClient; // Feign调用账户服务
/**
* AT模式: 创建订单 + 扣减库存 + 扣减余额
*/
@Override
@GlobalTransactional(name = "order-create-transaction",
rollbackFor = Exception.class)
public void createOrder(OrderDTO orderDTO) {
log.info("开启全局事务, XID={}", RootContext.getXID());
// 1. 创建订单 (本地事务)
Order order = new Order();
order.setOrderNo(orderDTO.getOrderNo());
order.setUserId(orderDTO.getUserId());
order.setAmount(orderDTO.getAmount());
orderMapper.insert(order);
log.info("订单创建成功, orderId={}", order.getId());
// 2. 扣减库存 (远程调用 - 分布式事务)
inventoryClient.deduct(orderDTO.getSkuId(), orderDTO.getQuantity());
log.info("库存扣减成功");
// 3. 扣减账户余额 (远程调用 - 分布式事务)
accountClient.deduct(orderDTO.getUserId(), orderDTO.getAmount());
log.info("余额扣减成功");
// 任何一步失败, Seata自动回滚所有操作
// 无需手动编写补偿逻辑!!!
}
}
库存服务:
java
@Service
public class InventoryServiceImpl implements InventoryService {
@Autowired
private InventoryMapper inventoryMapper;
@Override
public void deduct(Long skuId, Integer quantity) {
log.info("扣减库存, skuId={}, quantity={}, XID={}",
skuId, quantity, RootContext.getXID());
// Seata AT模式会自动生成undo_log
int rows = inventoryMapper.deduct(skuId, quantity);
if (rows == 0) {
throw new BusinessException("库存不足");
}
}
}
Seata配置:
yaml
seata:
enabled: true
application-id: order-service
tx-service-group: default_tx_group
service:
vgroup-mapping:
default_tx_group: default
grouplist:
default: localhost:8091 # Seata Server地址
config:
type: nacos
nacos:
server-addr: localhost:8848
namespace: seata
group: SEATA_GROUP
data-id: seataServer.properties
registry:
type: nacos
nacos:
server-addr: localhost:8848
namespace: seata
group: SEATA_GROUP
application: seata-server
4.5.4 TCC模式详解
TCC三个阶段:
- Try: 尝试执行,预留资源 (如冻结库存、冻结余额)
- Confirm: 确认执行,提交事务 (扣减冻结的库存、余额)
- Cancel: 取消执行,释放资源 (释放冻结的库存、余额)
TCC工作流程:
账户服务 (TCC) 库存服务 (TCC) Seata Server 订单服务 账户服务 (TCC) 库存服务 (TCC) Seata Server 订单服务 alt [全部Try成功] [任一Try失败] 1. 开启全局事务 2. 返回XID 3. Try: 冻结库存10个 stock=100, frozen=10 4. Try成功 5. Try: 冻结余额100元 balance=1000, frozen=100 6. Try成功 7. 提交全局事务 8. Confirm: 扣减冻结库存 stock=90, frozen=0 8. Confirm: 扣减冻结余额 balance=900, frozen=0 9. 回滚全局事务 10. Cancel: 释放冻结库存 stock=100, frozen=0 10. Cancel: 释放冻结余额 balance=1000, frozen=0
代码示例:
java
/**
* TCC接口定义
*/
@LocalTCC
public interface AccountTccService {
/**
* Try: 冻结余额
*/
@TwoPhaseBusinessAction(
name = "accountTry",
commitMethod = "commit",
rollbackMethod = "rollback"
)
boolean tryDeduct(
@BusinessActionContextParameter(paramName = "userId") Long userId,
@BusinessActionContextParameter(paramName = "amount") BigDecimal amount,
@BusinessActionContextParameter(paramName = "orderId") Long orderId
);
/**
* Confirm: 扣减冻结的余额
*/
boolean commit(BusinessActionContext context);
/**
* Cancel: 释放冻结的余额
*/
boolean rollback(BusinessActionContext context);
}
/**
* TCC实现
*/
@Service
public class AccountTccServiceImpl implements AccountTccService {
@Autowired
private AccountMapper accountMapper;
@Autowired
private AccountFreezeLogMapper freezeLogMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public boolean tryDeduct(Long userId, BigDecimal amount, Long orderId) {
log.info("Try: 冻结余额, userId={}, amount={}, orderId={}", userId, amount, orderId);
// 1. 检查余额是否充足
Account account = accountMapper.selectById(userId);
if (account.getBalance().compareTo(amount) < 0) {
throw new BusinessException("余额不足");
}
// 2. 冻结余额 (UPDATE account SET frozen = frozen + 100 WHERE userId = ?)
int rows = accountMapper.freeze(userId, amount);
if (rows == 0) {
throw new BusinessException("冻结余额失败");
}
// 3. 记录冻结日志 (幂等性、防悬挂、防重复)
AccountFreezeLog freezeLog = new AccountFreezeLog();
freezeLog.setUserId(userId);
freezeLog.setAmount(amount);
freezeLog.setOrderId(orderId);
freezeLog.setXid(RootContext.getXID());
freezeLog.setState("TRY");
freezeLogMapper.insert(freezeLog);
return true;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean commit(BusinessActionContext context) {
Long userId = context.getActionContext("userId", Long.class);
BigDecimal amount = context.getActionContext("amount", BigDecimal.class);
String xid = context.getXid();
log.info("Confirm: 扣减冻结余额, userId={}, amount={}, xid={}", userId, amount, xid);
// 1. 幂等性判断: 检查是否已经Confirm
AccountFreezeLog freezeLog = freezeLogMapper.selectByXid(xid);
if (freezeLog == null) {
return true; // 已Confirm,直接返回
}
if ("CONFIRM".equals(freezeLog.getState())) {
return true; // 已Confirm,幂等返回
}
// 2. 扣减余额 (UPDATE account SET balance = balance - 100, frozen = frozen - 100)
accountMapper.deduct(userId, amount);
// 3. 更新冻结日志状态
freezeLog.setState("CONFIRM");
freezeLogMapper.updateById(freezeLog);
return true;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean rollback(BusinessActionContext context) {
Long userId = context.getActionContext("userId", Long.class);
BigDecimal amount = context.getActionContext("amount", BigDecimal.class);
String xid = context.getXid();
log.info("Cancel: 释放冻结余额, userId={}, amount={}, xid={}", userId, amount, xid);
// 1. 幂等性判断
AccountFreezeLog freezeLog = freezeLogMapper.selectByXid(xid);
if (freezeLog == null) {
return true; // 空回滚,直接返回
}
if ("CANCEL".equals(freezeLog.getState())) {
return true; // 已Cancel,幂等返回
}
// 2. 释放冻结余额 (UPDATE account SET frozen = frozen - 100)
accountMapper.unfreeze(userId, amount);
// 3. 更新冻结日志状态
freezeLog.setState("CANCEL");
freezeLogMapper.updateById(freezeLog);
return true;
}
}
TCC模式关键点:
- 幂等性: Try/Confirm/Cancel可能被重复调用,必须保证幂等
- 防悬挂: Cancel先于Try执行 (如Try超时,TC调用Cancel,但Try还在执行)
- 防重复: Confirm/Cancel可能被重复调用
- 资源预留: Try阶段预留资源,Confirm阶段提交,Cancel阶段释放
小结
第四部分深度解析了阿里巴巴微服务生态的核心组件:
-
✅ Dubbo: 高性能RPC框架
- Dubbo协议 vs HTTP vs gRPC对比
- 负载均衡策略 (Random, RoundRobin, LeastActive, ConsistentHash, ShortestResponse)
- 集群容错 (Failover, Failfast, Failsafe, Failback, Forking, Broadcast)
- 性能优势: QPS 10万+ (3-5倍于OpenFeign)
-
✅ Nacos深度解析:
- AP/CP双模式架构 (Distro协议 + Raft协议)
- 临时实例 vs 持久化实例
- 配置管理: Namespace → Group → Data ID层级
- 配置优先级、动态刷新、灰度发布、版本回滚
-
✅ Sentinel深度解析:
- 流量控制 (直接、关联、链路限流)
- 流控效果 (快速失败、Warm Up、排队等待)
- 熔断降级 (慢调用比例、异常比例、异常数)
- 系统负载保护 (CPU、Load、RT、Thread、QPS)
- Sentinel Dashboard实时监控
- 规则持久化到Nacos
-
✅ RocketMQ:
- 架构: NameServer + Broker + Producer + Consumer
- 消息类型: 普通、顺序、事务、延时、批量
- 事务消息: Half Message + 本地事务 + 事务回查
- 消费模式: 集群消费 vs 广播消费
- 性能对比: RocketMQ vs Kafka vs RabbitMQ
-
✅ Seata:
- 三大角色: TC (协调器) + TM (管理器) + RM (资源管理器)
- AT模式: 自动补偿,undo_log机制,无代码侵入
- TCC模式: Try-Confirm-Cancel,手动补偿,高性能
- 模式对比: AT vs TCC vs SAGA vs XA
- 幂等性、防悬挂、防重复设计
关键结论:
阿里巴巴微服务生态是Spring Cloud Alibaba的核心竞争力:
- 🌟 Dubbo: 性能3-5倍于HTTP REST,适合内部服务调用
- 🌟 Nacos: 服务注册+配置中心二合一,功能强大
- 🌟 Sentinel: 流量防护、熔断降级、系统保护全覆盖
- 🌟 RocketMQ: 事务消息解决分布式事务,延时消息支持定时任务
- 🌟 Seata: AT模式简单易用,TCC模式性能优秀