共计 2477 个字符,预计需要花费 7 分钟才能阅读完成。
背景痛点:为什么需要微服务
最近在维护公司老项目时,每次上线新功能都像在走钢丝——明明只改了订单模块,支付功能却莫名其妙挂了。这种单体架构(Monolithic Architecture)的典型问题,在用户量突破 10 万后彻底爆发:

- 凌晨促销活动时,商品详情页的 CPU 占用直接飙到 90%,连带拖垮整个系统
- 所有功能打包部署,每次迭代需要全量回归测试,发布周期长达 3 小时
- 技术栈被老旧框架绑架,想引入 Redis 缓存都得考虑兼容性问题
这时候才真正体会到微服务(Microservices)的价值:把电商系统拆分成订单、支付、库存等独立服务,每个服务可以:
- 独立开发部署,用最适合的技术栈(比如用 Go 写高并发库存服务)
- 根据业务重要性差异化扩容(促销时给商品服务多分配服务器)
- 故障隔离,某个服务崩溃不影响核心链路
技术选型:Alibaba 还是 Netflix?
刚开始调研时,发现 Spring Cloud 有两个主流生态:
- Netflix 系:Eureka(服务发现)+Hystrix(熔断)+Zuul(网关)
- Alibaba 系:Nacos(服务发现)+Sentinel(熔断)+Seata(事务)
经过两周的对比测试,最终选择 Alibaba 方案,关键原因:
- Nacos 的配置管理(Configuration Management)比 Eureka 的纯注册中心更实用
- Sentinel 的流量控制规则支持动态生效,而 Hystrix 需要重启
- Seata 的 AT 模式对代码侵入性小,适合老系统改造
特别提醒:如果已经用了 Consul 做服务发现,可以单独引入 Sentinel 做熔断,不必整套替换。
核心实现三步走
1. Nacos 服务注册发现
在父 pom 引入 Spring Cloud Alibaba 依赖后,服务注册只需两步:
- 在 application.yml 添加配置(注意 namespace 用于环境隔离):
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.1.100:8848
namespace: dev
application:
name: order-service
- 启动类添加
@EnableDiscoveryClient注解
实测发现服务列表有延迟?调整心跳间隔(默认 30 秒):
spring.cloud.nacos.discovery.heart-beat-interval: 10
2. Sentinel 熔断降级
以支付服务调用银行接口为例,配置 QPS 阈值为 100 的流控规则:
@RestController
@RequestMapping("/payment")
public class PaymentController {
// 资源名需唯一
@SentinelResource(value = "bankApi", blockHandler = "handleFlowLimit")
@PostMapping("/create")
public Result createPayment(@RequestBody Order order) {// 调用银行 API 逻辑}
// 触发流控时执行的方法
public Result handleFlowLimit(Order order, BlockException ex) {return Result.error("当前交易人数过多,请稍后重试");
}
}
在 Sentinel 控制台配置规则:
- 资源名填写
bankApi - 阈值类型选 QPS,单机阈值设为 100
- 流控模式选直接(Direct)
3. Seata 分布式事务
处理跨服务的订单创建→扣库存→支付流程,使用 AT 模式:
sequenceDiagram
participant Client
participant OrderService
participant StorageService
participant PayService
Client->>OrderService: 创建订单
OrderService->>Seata: 开启全局事务(XID=123)
OrderService->>StorageService: 扣减库存(XID=123)
StorageService->>Seata: 注册分支事务
OrderService->>PayService: 发起支付(XID=123)
PayService->>Seata: 注册分支事务
Seata->>OrderService: 提交 / 回滚(XID=123)
关键配置:
# 使用 MySQL 作为事务日志存储
seata.store.mode=db
seata.store.db.datasource=druid
seata.store.db.url=jdbc:mysql://127.0.0.1:3306/seata
性能压测数据
用 JMeter 模拟 1000TPS 并发,持续 30 分钟的测试结果:
| 组件 | CPU 占用 | 内存消耗 | 网络 IO |
|---|---|---|---|
| Nacos 集群 | 45% | 2.3GB | 8MB/s |
| Sentinel | 12% | 500MB | 3MB/s |
| Seata-Server | 28% | 1.2GB | 5MB/s |
发现 Nacos 内存泄漏?升级到 2.0.4 版本后稳定在 1.8GB 以内。
生产环境避坑指南
Nacos 集群脑裂问题
现象:三个节点间网络分区后,出现多个 Leader 写入冲突。
解决方案:
- 使用至少 3 个节点(Quorum 机制)
- 配置数据库持久化(不依赖本地文件)
- 设置心跳超时时间:
nacos.naming.clean.initial-delay-ms=30000
Sentinel 规则持久化
默认规则存在内存中,重启后丢失。推荐两种方案:
- 推模式:通过 Nacos 配置中心同步规则
- 拉模式:在应用启动时调用 Sentinel API 初始化
Seata 全局锁冲突
高并发下可能出现 Global lock wait timeout 错误,优化方向:
- 减少全局锁持有时间(避免事务内远程调用)
- 修改默认锁超时时间(默认 30 秒):
seata.tm.degrade-check-period=2000
思考题
当用户重复提交订单时,如何保证:
1. 订单服务生成唯一订单号
2. 支付服务防止重复扣款
3. 库存服务避免超卖
欢迎在评论区分享你的分布式幂等性设计方案。
