读:理论靠谱,生产翻车的六个集成模式
目录
开篇:集成不是连上了就行
企业系统的集成问题有一个共同规律:上线初期看着没问题,跑一阵子才开始出事。原因是流量涨了、各系统各自迭代了、之前没预料到的场景出现了,这些在设计阶段都没考虑到。
Priyanka Jayavel 在 DZone 上的文章 6 Integration Patterns That Look Good on Paper and What Happens When They Hit Production 分析了六个几乎每个架构都会遇到的集成模式,指出它们在生产中实际翻车的方式。这篇笔记记下要点。
1. Request-Response(同步 API)
一个系统调用另一个系统接口,等着拿到结果再继续。
这种模式在响应时间可控时很可靠。问题在于依赖链:当一个 API 内部要串行调用多个下游系统时,链条中任何一个节点变慢,整条链都会被拖垮。支付场景最典型:订单服务依次调用库存、定价、物流、税务四个系统。税务系统响应从 200ms 涨到 5 秒会导致整条链超时,上游调用方全部收到超时报错(HTTP 504)。
同步调用设计起来最简单,但在依赖链面前也最脆弱。它适合响应时间可预测的场景,不适合长流程和多层依赖。
2. Event-Driven(事件驱动 / 发布订阅)
一个系统发布事件,多个系统独立响应。比如,客户下单后,"订单创建"事件同时触发库存扣减、邮件通知、物流发件。各系统互不等待,耦合度低。
翻车点集中在两个地方。
重复消费 :消息队列的重复投递或消费者崩溃后重试都可能导致事件消息被重复消费。这类问题没有明显的报错,但数据已经乱了。
顺序依赖 :比如业务逻辑假设"订单创建"事件总比"支付完成"先到达,但消息队列可能不保证跨分区的顺序(Kafka 不同 partition 之间),那么这个假设就可能被打破。
事件驱动不是"用了消息队列就自动解耦"。消费者必须做幂等处理,事件的消息格式和版本需要生产方和消费方约定好,改动时两边同步。
3. Scatter-Gather(并行聚合)
一个请求拆成多个并行调用,结果汇总后返回。比如Dashboard API会 同时从订单系统、客户系统、物流系统拉数据,合并后展示。
并行调用在所有下游系统都稳定时确实能提高性能。但只要有一个系统慢,整个响应就被拖住。两个系统 100ms 返回,第三个 10 秒才返回,用户体验到的就是 10 秒。并行化暴露的是最慢的那个依赖。
如何部分失败也需要提前想清楚。一个下游系统返回错误时,是返回不完整的结果,还是整体失败?这个决策影响面很大,设计阶段往往被忽略。
4. Retry(重试)
重试最危险的地方在于:如果操作不是幂等的,重试会导致很严重的事件。支付请求被重试了三次,用户被扣了三笔。这种事在生产中反复出现。
更隐蔽的问题是重试风暴。下游系统已经因为负载过高而变慢,上游的重试机制又给它加了三倍流量,导致它更慢,触发更多重试。正反馈回路,系统自己把自己打死了。
有效的重试需要两个配套:操作本身必须幂等(重复执行结果一样),重试策略需要退避机制(指数退避)和上限。
5. API Facade(API 统一入口)
一个统一的 API 层隐藏后端多个系统。"客户 API"提供一个端点,背后分别调 CRM、计费、客服三个系统。客户端只对接一个 API,不用关心后端的复杂性。
统一入口最大的坑是越做越多。一开始只做数据聚合和格式转换,后来加校验、加业务逻辑、加编排、加转换规则。统一入口变成了大杂烩,承载了太多不属于它的职责。改任何一个后端系统的接口都可能影响它,它本身变成了瓶颈。
统一入口应该只做简化访问这一件事。如果里面的逻辑特别多,说明架构出了问题。
6. Orchestration vs. Choreography(编排 vs. 协调)
管理分布式工作流的两种思路。
编排(Orchestration) :一个中心服务控制整个流程。订单服务依次调用支付、库存、物流。流程清晰,容易理解,出问题知道卡在哪一步。但中心服务本身成了瓶颈和单点。
协调(Choreography) :每个服务独立响应事件。订单事件触发支付,支付事件触发库存,库存事件触发物流。没有中心依赖,扩展性好。但端到端流程难以追踪,一个事件丢了,后续流程静默停止,没人知道。
两种方式没有绝对的优劣。编排适合需要强控制、流程清晰的场景;协调适合高吞吐、松耦合的场景。实际中往往是混合使用:核心流程用编排保证可追踪性,非核心流程用协调降低耦合。
总结
六个模式的设计假设和生产现实之间有差距,但差距的原因是相似的:设计阶段只考虑了正常路径,没有考虑部分失败、负载变化、各系统各自迭代这些生产环境的常态。集成架构真正要解决的问题是:出问题时能知道哪里断了、为什么断以及怎么恢复。