微服务架构及常见问题小结
一、什么是微服务架构
1、微服务架构
微服务架构是把单体应用拆分成多个可独立部署、独立运行、松耦合、小而专的服务,通过网络协议(RPC/HTTP)协同工作的分布式架构。
核心目标:
- 独立迭代、独立扩缩容
- 高可用、容错、可治理
- 技术栈异构(适度)
核心特征:
- 单一职责:一个服务只做一件事
- 独立部署:互不影响
- 独立数据库(关键)
- 松耦合:通过接口契约通信
- 自动化运维:CI/CD、容器化
- 高可用容错:熔断、降级、隔离
- 可观测性:日志、链路、监控
2、核心组件
- Gateway:统一入口、路由、鉴权、限流
- Nacos:服务注册发现、配置中心
- Sentinel:限流、熔断、降级、防雪崩
- Dubbo/Feign:服务远程调用
- RocketMQ:异步解耦、削峰、最终一致性
- Seata:分布式事务
- SkyWalking:全链路追踪、排查问题
3、设计原则
微服务架构设计原则主要围绕解耦、自治、高可用:
- 按业务领域拆分,单一职责、高内聚低耦合;
- 一服务一数据库,不跨服务联表;
- 服务无状态,支持水平扩展;
- 异步优先,减少强依赖;
- 必须做容错设计:限流、熔断、降级、超时、幂等;
- 全链路可观测,便于排查问题。
4、与单体架构区别
第一,架构边界不同:单体是一个进程、一个库;微服务按业务拆分多服务、多独立数据库。
第二,故障与发布隔离性不同:单体一处故障全系统不可用,发布必须全量;微服务故障隔离、可独立发布。
第三,扩展能力不同:单体只能整体扩容,微服务可局部弹性扩容。
第四,复杂度不同:单体简单但后期维护难;微服务解决高并发与迭代效率,但带来分布式事务、链路追踪、服务治理等复杂问题。
5、微服务拆分
(1) 适合单体架构的应用
- 小型项目、初创项目
- 业务简单、无并发
- 团队人数少(<5 人)
追求快速上线,无运维能力 → 这类用单体,效率最高
(2) 适合做微服务架构的应用
- 业务复杂、模块多、耦合严重,需要分团队维护;
- 高并发、流量大,需要局部弹性扩容;
- 要求快速迭代、独立发布,不影响其他模块;
- 对高可用、故障隔离要求高,不能全盘崩溃;
- 追求模块自治、松耦合。
满足以上条件的应用才需要微服务拆分。
二、核心架构问题
1、网络不可靠(超时、重试、丢包)
本质:从本地方法调用 → 网络 RPC,网络不可靠
问题:
- 调用超时
- 重复调用
- 数据丢失
解决方案:
- 超时 + 重试(读接口)
- 幂等性设计(防重复)
- 异步化、消息解耦
2、分布式事务(保证数据的最终一致性)
本质:跨服务、跨库,本地事务失效
解决方案:
- Seata AT(无侵入,普通业务,基于本地事务 + undo_log)
- Seata TCC(高并发核心,适合核心支付 / 库存,需要手动编码 Try/Confirm/Cancel)
- RocketMQ 事务消息(最终一致性,高并发首选)
- 业务补偿、状态机
生产经验:非核心业务用最终一致性(MQ 消息),核心交易用 Seata AT。
3、服务间通讯
服务间通讯主要分为同步和异步两类:
- 同步采用 Dubbo(RPC)或 OpenFeign(HTTP),用于实时调用;
- 异步采用 RocketMQ等,用于解耦、削峰、最终一致性。
其中,强依赖用同步,非强依赖用异步。
通信过程中要解决服务雪崩、分布式事务、接口幂等三大问题,通过 Sentinel 熔断限流、Seata/MQ 事务、幂等设计 保证高可用。
4、分布式锁
微服务是多实例、多进程、跨 JVM的,本地锁无效,需要使用分布式锁。尤其在以下场景中要注意分布式锁的问题:
- 秒杀超卖
- 重复提交
- 分布式任务重复执行
- 并发更新数据一致性
目前,生产主流用 Redis + Redisson(官方框架),核心是 SET NX PX 原子命令,必须设置过期时间和唯一标识,防止死锁和误删锁。Redisson 提供可重入、看门狗自动续期,简化开发。强一致性场景用 Zookeeper 分布式锁,简单低并发用 MySQL 锁。
PS:Redis看门狗就是给快到期的锁自动续期,保证业务执行完前锁不会自动释放
5、幂等性
幂等就是同一请求多次执行结果一致。微服务存在网络重试、MQ 重复投递、重复提交,必须做幂等,否则会出现数据重复、超卖、脏数据。
常用的幂等性方案有:
- 唯一业务 ID + 唯一索引(最常用),适用于下单、支付、消息消费
- Redis Token 防重,适用于表单重复提交、秒杀
- 状态机/状态流转控制,适用于订单、支付、物流
- 乐观锁版本号,适用于并发更新数据
6、分布式ID
分布式ID是分布式系统中,全局唯一的 ID。用来标识订单、支付流水、用户、消息、日志等。
核心要求是:
- 全局唯一(不重复)
- 趋势递增(MySQL 索引友好)
-
高可用
-
高性能
- 安全(不暴露业务量)
主流的方案有:
- UUID,简单,本地生成、无网络消耗,但其太长、无序、MySQL 索引性能极差,不能用于订单 ID / 业务 ID
- 数据库自增,有序、简单,但DB 压力大、扩容难、有宕机风险。小项目可用,高并发不用
- 雪花算法,使用1位符号 + 41位时间戳 + 10位机器ID + 12位序列号的结构,优点是有序、long 型、性能极高、不依赖中间件,但依赖机器时钟(时钟回拨会导致ID重复)
- 美团 Leaf / 百度 UidGenerator,基于号段模式 + 雪花优化,优点是高可用、解决时钟回拨
PS:时钟回拨是服务器时间同步导致时间倒退,会造成 ID 重复。
生产常用以下解决方案:
- 回拨时间极短,等待时间追上;
- 回拨较大,使用历史时间戳 + 序列递增,不使用当前时间,直到系统时间追上来。开源框架如Leaf、UidGenerator都采用这种历史时间戳方案,能彻底解决回拨问题。
三、微服务性能优化
微服务性能优化从全链路展开:
- 调用层用 Dubbo、异步并行、缩短调用链;
- 异步化用 MQ 削峰解耦;
- DB 优化索引、分库分表、加缓存;
- 优化 JVM、线程池、连接池;
- 用 Sentinel 限流熔断防止雪崩;
- 架构上做无状态、水平扩展、宽表冗余。
整体目标是减少网络开销、降低 DB 压力、避免阻塞、提升并发。具体如下:
1. 服务调用优化(最核心)
- Dubbo 替换 OpenFeign(TCP 长连接、二进制序列化,性能提升数倍)
- 同步调用改异步并行调用
- 减少链式过长调用,能合并就合并
- 合理设置超时时间,避免慢调用拖死系统
2. 网关层优化
- Gateway 合理设置线程数、超时、限流
- 开启缓存路由、减少断言判断
- 静态资源直接走 CDN,不走网关
3. 注册 / 配置中心优化(Nacos)
- 合理调整心跳、剔除、注册缓存
- 关闭无效推送,减少服务抖动
- 生产使用集群模式
4. 异步化 & MQ 削峰
- 能异步绝不同步:日志、通知、数据同步
- 使用RocketMQ异步解耦
- 批量消费、提高消费线程、优化慢消费
5. 数据库性能优化(重中之重)
- 加索引、避免慢 SQL
- 分库分表、读写分离
- 禁止大事务、禁止跨服务事务
- 合理使用Redis 缓存减轻 DB 压力
6. 缓存架构优化
- 本地缓存 Caffeine → 分布式缓存 Redis
- 缓存预热、过期、降级
- 解决:缓存穿透、击穿、雪崩
- 热点数据单独缓存
7. 服务资源优化
- JVM GC 优化,减少 FullGC
- 线程池参数合理(核心、最大、队列)
- 连接池优化(DB、HTTP、Redis)
- 避免内存泄漏、大对象
8. 高可用防护(避免性能雪崩)
- Sentinel 限流、熔断、降级
- 线程隔离
- 读接口重试,写接口快速失败
- 接口幂等,安全重试
9. 架构层面优化
- 按领域拆分,避免单体微服务
- 无状态设计,水平扩容
- 构建宽表,减少跨服务查询
- 读写分离 CQRS
四、生产问题排查
1、服务雪崩
服务雪崩:未做熔断降级,流量打满所有服务
本质:一个服务故障 → 级联传导 → 整个链路不可用
原因:同步调用、阻塞、超时、资源耗尽
解决方案:
- 加超时控制
- Sen嗯停了、熔断、降级
- 线程隔离
- 读接口重试机制,写接口快速失败
2、分布式事务不一致
现象:订单创建了,库存没扣 / 支付成功状态没改
原因:网络异常、服务宕机、超时
解决方案:
- Seata AT 保证最终一致(详见Spring CLoud Alibaba相关知识总结)
- 核心场景 TCC
- 高并发用 RocketMQ 事务消息
- 状态机 + 定时任务校对
3、接口重复调用 / 重复提交
现象:重复下单、重复扣款、重复发券
原因:网络重试、前端重复点、MQ 重投
解决方案:
- 全局幂等设计
- 唯一索引、token 防重、状态机
4、分布式 ID 重复
现象:主键冲突、订单号重复
原因:雪花算法时钟回拨
解决方案:
- 时钟回拨等待 / 历史时间戳续跑
- 使用美团 Leaf / 百度 UidGenerator
5、服务上下线抖动 / 调用报错
现象:发布时大量超时、报错
原因:Nacos 心跳延迟、摘流不及时
解决方案:
- 优雅上下线(先摘流再停机)
- 延长预热时间
- 调整心跳与剔除超时
6、内存泄漏 / FullGC 频繁
现象:CPU 高、响应慢、突然宕机
原因:线程池用完、连接未释放、大对象
解决方案:
- jstack、jmap 排查
- 检查 ThreadLocal、连接池
- 优化 GC 参数
7、配置刷新导致服务抖动
现象:Nacos 配置变更,部分服务异常
原因:动态刷新 @RefreshScope 不安全
解决方案:
- 关键配置不动态刷新
- 重启生效
- 灰度推送配置
8、全链路排查困难
现象:接口超时,但不知道哪一步卡
解决方案:
- SkyWalking Pinpoint
- TraceId 透传
- 日志统一格式
- 监控告警(RT、异常、QPS)
更多推荐

所有评论(0)