微服务架构与 Spring Cloud Alibaba 实战:注册发现、配置中心、网关、限流与分布式事务

微服务架构与 Spring Cloud Alibaba 实战:注册发现、配置中心、网关、限流与分布式事务
神经蛙Spring Boot 解决的是”怎么又快又好地写一个服务”,Spring Cloud 解决的是”一堆服务怎么协同、治理、不互相拖垮”。本文不重复 Spring Boot 自动装配、JVM 调优、并发编程那些已经写过的点,只聚焦”服务拆分之后那些绕不开的分布式基础设施”,并用 Spring Cloud Alibaba 这套国内最主流的落地方案串起来。
一、为什么需要微服务:从单体到分布式
早期一个 war 包打天下:Controller、Service、DAO 全在一个进程里,改一行要整体重发。业务小的时候很爽,大了就有三个典型痛点。
- 扩展只能整体扩:下单模块 CPU 打满,却被迫连不忙的用户模块一起加机器,浪费资源。
- 技术栈被锁死:想用 Go 写实时推送?不行,单体是 Java 一统天下。
- 发布互相牵连:改个文案的手抖,可能把支付一起带崩。
微服务的核心思想就八个字:拆得开、各自治、独立发。每个服务拥有自己的进程、数据库、迭代节奏,通过 RPC/HTTP 协作。
但微服务不是银弹。它把”进程内的函数调用”变成了”跨网络的远程调用”,代价是:网络不可靠、数据要一致、链路要可观测、运维复杂度指数级上升。康威定律提醒我们:微服务边界 = 团队沟通边界,团队只有三五个人时,硬上微服务往往是灾难。
二、微服务核心基础设施全景
一个能跑起来的微服务集群,至少要有下面这几块能力。先建立全局认知,后面逐个击破:
| 能力 | 要解决的问题 | Spring Cloud Alibaba 选型 |
|---|---|---|
| 服务注册与发现 | 服务地址不再硬编码,动态上下线 | Nacos Discovery |
| 统一配置中心 | 配置外置、动态刷新、多环境隔离 | Nacos Config |
| 服务通信 | 声明式、带负载均衡地调用他人 | OpenFeign + Spring Cloud LoadBalancer |
| API 网关 | 统一入口、鉴权、限流、路由 | Spring Cloud Gateway |
| 容错限流 | 防止雪崩,熔断降级 | Sentinel |
| 分布式事务 | 跨服务的数据一致性 | Seata(AT 模式) |
| 链路追踪 | 一次请求穿过 N 个服务,如何定位慢点 | Micrometer Tracing / SkyWalking |
三、服务注册与发现:Nacos
没有注册中心时,A 调 B 得写死 http://192.168.1.23:8081/api。B 一扩容、一换 IP,A 就得跟着改、重新发版——这在分布式环境里不可接受。
Nacos 把”地址表”收归中心:每个服务启动时把自己的 IP、端口、健康状态注册上去;调用方拉取可用实例列表,再挑一个发起请求。
1 | # 服务提供者 / 消费者 共有配置 |
1 |
|
几个关键点:
- 临时实例 vs 持久实例:临时实例靠心跳保活,掉线即剔除(默认);持久实例注册在 Nacos 磁盘,适合核心中间件。
- 健康检查:Nacos 对临时实例做心跳探测,对持久实例做主动 TCP/HTTP 探测。
- CAP 取向:Nacos 在临时实例下偏向 AP(高可用、最终一致),持久实例可切 CP。
调用方拿到的实例列表是”带过期时间的本地缓存 + 定时轮询”组合,所以某个实例刚挂时,调用方最多”盲调”一小段时间才会被剔除——这正是后面要加容错兜底的原因。
四、统一配置中心:Nacos Config
把 application.yml 写死在 jar 里,改个开关就要重新打包发布,灰度、回滚都别想了。Nacos Config 把配置搬到服务端,应用启动时拉取,并支持动态刷新。
定位一个配置需要三个坐标:
| 坐标 | 作用 | 示例 |
|---|---|---|
| Data ID | 具体配置文件名 | order-service.yaml |
| Group | 分组(默认 DEFAULT_GROUP) | ORDER_GROUP |
| Namespace | 环境/租户隔离(彼此不可见) | dev / prod |
1 |
|
实践建议:把数据库密码、开关、限流阈值等易变配置放 Nacos;把端口、应用名这类几乎不变的留本地。配置要带版本与回滚能力,敏感配置走加密插件。
五、服务通信:OpenFeign + LoadBalancer
用 RestTemplate 拼 URL 调别人,代码又臭又长还容易出错。OpenFeign 让你”像调本地接口一样调远程服务”——写一个接口加注解,框架帮你拼地址、负载均衡、发请求。
1 | // 指向注册中心里的服务名 |
- 负载均衡:Spring Cloud LoadBalancer 从 Nacos 拉到的实例列表中,按轮询/加权挑一个,天然支持横向扩容。
- 超时与重试:在
application.yml里配connectTimeout/readTimeout,并对非幂等写操作谨慎重试(重试可能放大故障)。 - 兜底: Feign 调用务必配合后面的 Sentinel 降级,否则一个慢依赖会把你的线程池拖穿。
六、API 网关:Spring Cloud Gateway
十个服务对外暴露十个域名?客户端要记十个地址、做十次鉴权?网关就是这十个服务的统一前台:所有流量先过网关,再由它按规则转发。
Gateway 的三大件:
- Route(路由):
ID + 目标 URI + 断言 + 过滤器,一条转发规则。 - Predicate(断言):匹配条件,如
Path=/order/**、Header、时间窗口。 - Filter(过滤器):对请求/响应做加工,如加头、限流、改写路径。
1 | spring: |
全局过滤器(GlobalFilter)是做统一鉴权、灰度标记、埋点、CORS 的最佳位置:一次写好,所有服务免重复。但别把重业务逻辑塞进网关——它本应是”薄薄一层转发”,变胖了反而成瓶颈。Gateway 基于 WebFlux 响应式模型,注意它和 Spring MVC 的 Tomcat 不是一套线程模型。
七、服务容错与限流:Sentinel
微服务最怕雪崩:A 调 B,B 调 C,C 慢了 → B 的线程被占满 → A 也被拖死 → 全盘 502。Sentinel 提供四把保护伞:
- 限流:QPS 或并发线程数超阈值就拒绝,保护自身。
- 熔断:被调方错误率/慢调用比例过高,直接”先断一段时间”,给对端喘息。
- 降级:资源不稳定时自动返回兜底,而非一直卡着。
- 隔离:信号量/线程池隔离,限制单个依赖占用的资源。
1 |
|
流控阈值类型分 QPS(每秒请求数)和线程数(并发占用);流控模式有”直接、关联、链路”三种,比如可让”写接口”被”读接口”关联限流,保护写库。阈值一定要靠压测得出,拍脑袋定的数字在真实流量面前毫无意义。
八、分布式事务:Seata
本地事务靠 @Transactional 一个方法内 ACID。可一旦下单要”扣库存 + 减余额 + 写订单”跨三个服务,本地事务就管不到别人了——中间某一步失败,前面已经提交的就成了脏数据。
常见方案对比:
| 方案 | 一致性 | 侵入性 | 适用场景 |
|---|---|---|---|
| 两阶段提交(2PC) | 强一致 | 中 | 传统数据库,锁资源久 |
| TCC | 强一致 | 高(写三套接口) | 资金等强一致核心 |
| Saga | 最终一致 | 中(写补偿) | 长流程业务 |
| 本地消息表 / 事务消息 | 最终一致 | 低 | 可异步的对账类 |
| Seata AT | 最终一致 | 极低(加注解) | 大多数业务首选 |
Seata 的 AT 模式对业务几乎零侵入:一阶段本地事务提交的同时,框架自动生成 before/after 镜像写入 undo_log;二阶段若全局提交就异步清理,若回滚就用 undo_log 反向补偿。
1 |
|
能用”最终一致”就别上”强一致”:优先把跨服务操作设计成可补偿、幂等的异步流程(如发消息 + 对账),Seata 只在确实需要强一致的关键链路启用。分布式事务越用越贵,能不跨服务就不要跨。
九、可观测性:让请求”可被看见”
拆成几十个服务后,一个慢请求到底卡在哪一跳?靠猜不行,要三件套:
- 链路追踪:给每次请求发一个全局
TraceId,跨服务透传,把各段耗时串成一条瀑布图(SkyWalking / Micrometer Tracing)。 - 指标(Metrics):QPS、RT、错误率、线程池水位,配告警阈值。
- 日志(Logging):统一采集,关键处打印
TraceId方便检索。
三者通过 TraceId 关联,是定位分布式问题的命脉。采样率别拉满(生产可按 1%~10% 采样),否则链路存储成本爆炸。
十、微服务 ≠ 银弹:什么时候不该上
| 维度 | 单体更合适 | 微服务更合适 |
|---|---|---|
| 团队规模 | 1~3 人 | 多团队、职责清晰 |
| 业务复杂度 | 简单、变化慢 | 模块多、迭代快 |
| 交付要求 | 一个包发完 | 各模块独立发布 |
| 运维能力 | 弱 | 有 CI/CD、监控、链路底座 |
Spring Boot 帮你”把每个服务写好”,Spring Cloud 帮你”把这些服务管好”。没有监控、没有配置中心、没有链路追踪就上微服务,等于蒙眼开赛车。
十一、生产避坑清单(10 条)
- 数据库按服务私有:坚决不跨服务直连别人的库,一律走接口;共享库是分布式耦合的最大根源。
- 能最终一致就别强一致:优先异步 + 补偿 + 对账,Seata 只在关键链路启用。
- 所有远程调用必须兜底:Feign + Sentinel 降级,避免一个慢依赖拖垮整条链路。
- 网关只做薄转发:鉴权/灰度/CORS 放全局过滤器,重业务逻辑别塞进去。
- 限流阈值靠压测定:QPS/线程数阈值拍脑袋 = 线上事故,务必基于真实容量。
- 注册中心要高可用:Nacos 至少集群部署,否则它挂了全集群”失明”。
- 配置要可回滚:Nacos 配置变更带版本,敏感项加密,变更走审批。
- 接口要幂等:网络重试、消息重投无处不在,写接口靠唯一键/Token 防重复。
- 链路追踪采样的度:全量采集成本太高,按业务重要度分级采样。
- 服务粒度别过细:按”能独立部署、独立扩容、独立Owner”切,别切到”一个接口一个服务”的自我感动。














