如何选通信方案
Category
networking / IPC。节点定位:四步选型顺序——定义语义 → 判断命令还是事件 → 按性质选方案 → 再看非功能成本。
Definition
通信方案选型最常见的失败,不是技术上做不到,而是问题还没定义清楚就开始比组件。Kafka、RabbitMQ、Redis Stream、gRPC、进程内队列、任务系统都各有价值,但它们适合的是不同语义。只按产品品牌选,最后通常会得到一套“能跑,但解释不了为什么这样跑”的系统。
真正可靠的选型顺序,应该永远先于中间件名词。
Problem
问题没定义清楚就开始比组件,最后得到「能跑但解释不了为什么这样跑」的系统——选型返工大多源于此。
第一步先定义链路语义
在讨论任何方案前,先把下面几件事写清楚:
- 调用方是否必须同步拿到结果
- 单个消费者还是多个消费者
- 是否允许积压和延迟
- 是否必须保序
- 是否允许重复投递
- 失败后是立即报错、稍后重试还是人工补偿
如果这些问题还没回答,就去讨论 MQ、RPC 或事件总线,基本等于倒着做设计。
第二步判断这条链路更像命令还是更像事件
如果它更像命令,也就是“请你现在完成这件事并给我明确结果”,那通常更偏同步调用或同步入口加异步后处理。
如果它更像事件,也就是“这件事已经发生,你们按需处理”,那通常更偏事件广播、异步消费或发布订阅。
很多系统做坏,就是因为命令和事件被混用。调用方嘴上说自己在发事件,实际上却在等对方立刻给承诺。
第三步按链路性质选方案
进程内或同机高频协作
如果追求的是极低延迟、上下文共享和最小序列化成本,优先考虑进程内队列、本地事件总线或更轻的本地 IPC,而不是先上跨机 Broker。
强交互、需立即反馈的服务调用
这类链路通常更适合同步 RPC,因为调用方需要明确成功或失败,并且排障与链路可解释性比“看上去更解耦”更重要。
需要削峰、缓冲或多消费者扩散的链路
这类链路通常更适合 Broker 式消息系统,因为你真正要的不是一次函数调用,而是队列、持久化、订阅扩散和消费解耦。
耗时长但入口需要立即响应的链路
这类链路适合同步接收请求,再异步进入后台任务系统。关键不是换成异步就完了,而是要明确“请求已受理”和“任务已完成”是两件事。
第四步再看非功能性成本
即便链路语义匹配,方案还要接受下面这些现实成本校验:
- 部署和运维复杂度
- 协议兼容和版本演进成本
- 监控、追踪和排障能力
- 团队对该方案的熟悉程度
- 故障恢复、回放和审计支持
很多选型理论上正确,实际落地却失败,不是因为方案不行,而是团队没有准备好承担它附带的治理成本。
一个更实际的选型顺序
比较稳妥的顺序通常是:
- 先定义链路语义和失败代价。
- 再区分它是命令型还是事件型。
- 再判断它更偏低延迟还是更偏高吞吐。
- 最后才在候选组件里选最省治理成本的一种。
这个顺序的核心是,不让中间件能力反过来塑造业务边界。
不同方案真正擅长的事情
- 进程内事件总线擅长低成本模块解耦,但不擅长跨进程可靠治理。
- 同步 RPC 擅长明确交互和实时反馈,但不擅长削峰和多消费者广播。
- Broker 式 MQ 擅长异步解耦、削峰和扩散,但不擅长实时主链路控制。
- 后台任务系统擅长长耗时处理,但不适合伪装成立即完成的请求。
看清这些边界以后,很多选型其实不会太难。
常见误区
最常见的错误,是把选型做成产品对比,而不是问题对比。第二类错误,是因为某个中间件在公司里已有经验,就强行把所有链路都往同一种模型里塞。第三类错误,是方案选对了语义,却没有补足监控、回放、死信、重试和兼容治理,最后系统只有“能发消息”的能力,没有“能稳定运营”的能力。
实战案例:一次「先定中间件再找场景,四条链路推倒重来」的选型顺序倒置排查
案例为教学示例(非摘自真实项目),数字经过取整简化。它把本页「第一步先定义链路语义」「第三步按链路性质选方案」「第四步再看非功能性成本」用到深水区:顺序倒了,组件就反过来塑造业务——这是选型返工的顺序排查,也是「不让中间件能力反过来塑造业务边界」的完整展开。
背景与现象:某公司技术栈会拍板「所有新链路默认 Kafka」,12 条新链路立项直接套用,链路语义六问一条没答。上线后实例进出确认 P99 从 35 毫秒涨到 780 毫秒;周运维排障工单 45 起,回放补数 19 起、死信手工处理 14 起、重试风暴 12 起;4 条链路语义不匹配推倒重做,浪费 5 周,选型问题单合计 40 起。
第一步:现象与口径——反馈、治理、返工三笔账
反馈口径:实例进出确认 P99 从 35 毫秒涨到 780 毫秒——强交互链路却要先写主题、再等消费回执,排障与链路可解释性一起变差。
治理口径:周运维工单 45 起,其中回放补数 19 起、死信手工处理 14 起、重试风暴 12 起——19 + 14 + 12 = 45,全是没补治理能力的账。
返工口径:12 条立项里 4 条推倒重做、浪费 5 周;选型问题单 40 起构成归因基数。
第二步:分层归因——按本页四步逐项对
选型返工归因 占比
中间件品牌先行,问题没定义就比组件 45%
已有经验路径依赖,所有链路塞同一模型 35%
非功能成本未评估,监控回放死信缺失 20%逐项比对:第一步的语义六问(同步结果、单多消费、积压、保序、重复、失败去向)一条没答就进了第三步;第三步四类性质里「进程内或同机高频协作」「强交互、需立即反馈的服务调用」两类被硬套 Broker;第四步五项成本只考了「团队对该方案的熟悉程度」。40 起问题单逐项归位:18 + 14 + 8 = 40,账能闭合。
第三步:根因——顺序倒置,组件反过来定义了业务
本页 Problem 原话:问题没定义清楚就开始比组件,最后得到「能跑但解释不了为什么这样跑」的系统——选型返工大多源于此。根因是第一步被跳过:语义没定义就比组件,等于允许中间件能力反过来塑造业务边界。
第四步:处置与回填——把顺序正过来
- 顺序回正:立项先答语义六问与失败代价,再判命令还是事件,再定延迟或吞吐取向,最后才在候选组件里比治理成本。
- 方案按性质分:高频协作用进程内队列与本地事件总线,强交互用同步 RPC,削峰扩散用 Broker 式消息系统,长耗时用后台任务系统。
- 治理成本进验收:部署运维、协议兼容、监控排障、团队熟悉、故障回放五项不齐,不算选型完成。
复核账:实例进出确认 P99 780 毫秒 → 35 毫秒;返工链路 4 条 → 0 条(整改后新立项 12 条零返工);周运维工单 45 起 → 6 起。
回填清单:
| 回填项 | 动作 | 回填处 |
|---|---|---|
| 语义六问 | 同步结果、单多消费、积压、保序、重复、失败去向先写清 | 第一步先定义链路语义 |
| 命令事件判别 | 命令走同步入口,事件才走广播与异步消费 | 第二步判断这条链路更像命令还是更像事件 |
| 性质对号入座 | 高频协作、强交互、削峰扩散、长耗时四类各选各的方案 | 第三步按链路性质选方案 |
| 治理成本验收 | 运维、兼容、监控、熟悉度、回放五项不齐不结项 | 第四步再看非功能性成本 |
案例的三个教训
- 选型是问题对比,不是产品对比——品牌先行的系统能跑,但解释不了为什么这样跑。
- 公司经验是治理下限,不是形态答案——路径依赖会把所有链路塞进同一个模型。
- 语义对了再谈组件,治理不齐不算完成——顺序一旦倒置,组件就会反过来定义业务。
Used By
新链路立项评审;旧链路改造前的方案复核。
Related
上游:本树 IPC 各节点(01–05 是它的判断输入)。下游:开源服务器地图(server 树,组件选型落地)。关系链:链路语义 → 模式归类 → 方案 → 非功能复核。
Reference
本页为工程经验归纳;各组件能力以官方文档为准;页内实战案例为教学示例(数字取整简化)。