微服务里5种设计模式,GoF 书里没写但天天在用
GoF 的 23 种设计模式,学完之后你发现微服务里好多问题用不上。不是那些模式没用,是微服务的痛点跟单机应用不一样。
微服务架构里,你面临的不是"怎么抽象一个对象",而是"服务挂了怎么办"、"流量突然打进来怎么办"、"多个服务要一起操作怎么保证一致性"。
这些问题,GoF 书里没写,但有大佬总结了一套微服务设计模式。这才是你天天要用的东西。
1. 熔断器模式(Circuit Breaker)
你调一个下游服务,它慢了或者挂了,你的线程全卡在等响应上,最后你把上游也拖挂了。
熔断器干的事就是:下游不行了,就直接失败,别等。
```java // 用 Resilience4j 的熔断器 CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("orderService");
Supplier decoratedSupplier = CircuitBreaker .decorateSupplier(circuitBreaker, () -> orderService.getOrder(orderId));
// 熔断器打开时,直接走降级逻辑 String result = Try.ofSupplier(decoratedSupplier) .recover(throwable -> "默认订单数据") .get(); ```
熔断器有三个状态:
- 关闭:正常调下游
- 打开:下游挂了,直接失败,不调了
- 半开:等了一段时间,试一个请求,成功了就关闭,失败了继续打开
这个模式的核心是:快速失败比慢速成功更有价值。下游已经不行了,你还死撑着等超时,只会把问题放大。
2. API 网关模式(API Gateway)
微服务里每个服务都有自己的地址和端口,前端不可能直接调十几个服务。而且认证、限流、日志这些事,每个服务都做一遍太蠢了。
API 网关就是统一入口:所有请求先到网关,网关负责转发、认证、限流、日志。
前端 → API 网关 → 用户服务
→ 订单服务
→ 支付服务
Spring Cloud Gateway、Kong、Nginx 都能做网关。关键是:网关只做横切关注点(认证、日志、限流),业务逻辑全交给下游服务。
我见过有人把业务逻辑写在网关里,说"这样少一次网络调用"。结果网关变成了巨无霸,改一个逻辑影响所有服务。这不是优化,是架构灾难。
3. 服务发现模式(Service Discovery)
微服务部署在容器里,IP 和端口随时在变。你不可能把下游服务的地址写死在配置文件里。
服务发现干的事就是:服务启动时注册自己的地址,调用方从注册中心查地址。
订单服务启动 → 注册到 Consul/Eureka/Nacos
支付服务要调订单服务 → 从注册中心查订单服务的地址 → 发起调用
这跟 GoF 的代理模式(Proxy)有点像:调用方拿到的是一个"逻辑上的服务名",不是具体的地址。注册中心就是那个"代理",负责把服务名解析成真实地址。
Spring Cloud 里用 @LoadBalanced + RestTemplate,底层就是服务发现 + 负载均衡:
```java @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }
// 调用时直接用服务名,不用写 IP 和端口 restTemplate.getForObject("http://order-service/orders/" + orderId, Order.class); ```
4. 舱壁模式(Bulkhead)
你调三个下游服务:订单服务、支付服务、库存服务。库存服务慢了,你的线程全卡在等库存响应上,结果订单服务和支付服务也调不了了。
舱壁模式的名字来自船舱:一个舱漏水,不影响其他舱。
在代码里就是:不同的下游服务用不同的线程池。
```java // Resilience4j 的舱壁模式 ThreadPoolBulkhead orderBulkhead = ThreadPoolBulkhead .ofDefaults("orderService");
Supplier decorated = ThreadPoolBulkhead .decorateSupplier(orderBulkhead, () -> orderService.getOrder(id)); ```
订单服务的线程池满了,不影响支付服务的调用。每个下游有自己的"舱壁",一个挂了不拖垮全局。
这其实是对资源隔离的一种设计模式实践。你想想,如果不隔离,一个慢下游就能搞死你的整个服务。这跟数据库连接池的思路是一样的:不同业务用不同的连接池,一个业务把连接池打满了,不影响其他业务。
5. 事件驱动模式(Event-Driven)
微服务之间同步调用多了,耦合会越来越重。A 调 B,B 调 C,C 调 D,一个慢了全慢。
事件驱动模式干的事就是:把同步调用变成异步事件。
订单创建 → 发一个 "OrderCreated" 事件
→ 库存服务消费,扣库存
→ 支付服务消费,发起扣款
→ 通知服务消费,发短信
服务之间不直接调用,通过消息队列(Kafka、RabbitMQ)传递事件。下游服务挂了,上游不受影响;上游服务挂了,下游等它恢复后继续消费事件。
这跟 GoF 的观察者模式本质是一样的:发布者不知道有多少订阅者,订阅者也不知道发布者是谁,双方通过事件解耦。
但微服务的事件驱动比观察者模式复杂:要考虑消息丢失、重复消费、消息顺序、事务一致性。这也是为什么分布式系统比单机系统难那么多。
GoF 模式没过时,但不够用了
GoF 的 23 种模式教你怎么写"好维护的面向对象代码"。但微服务架构下,你面临的问题已经从"代码层面"上升到了"系统层面"。
熔断器、舱壁、服务发现,这些模式解决的不是"怎么写类",而是"怎么让分布式系统不崩"。
你先把 GoF 的模式用熟,再来学这些微服务模式,会发现有好多思想是相通的。代理模式 → 服务发现,观察者模式 → 事件驱动,适配器模式 → API 网关的协议转换。
设计模式不是孤立的,理解了思想,换一个场景你也能自己想出解法。
我在做一个用卡皮巴拉讲设计模式的微信小程序「爪爪代码冒险记」。GoF 的 23 种讲完之后,微服务设计模式也会加进去,毕竟这才是实际工作里天天碰到的东西。
188

被折叠的 条评论
为什么被折叠?



