4. 模块间通信方式
在微服务架构中,模块间的通信方式直接决定了系统的耦合度、可用性、数据一致性以及响应性能。本章聚焦于同步调用(REST / gRPC)与异步消息(Kafka / RabbitMQ)两大阵营,从企业级审批流场景出发,给出可落地的选型决策框架。
核心原则:没有绝对最优的通信方式,只有最适合当前业务场景的权衡。审批流中,命令(Command)与事件(Event)的分离是设计起点。
4.1 同步调用:REST vs gRPC
同步调用适用于强实时、低延迟、请求-响应模式。在审批流中,常用于“提交审批”、“驳回”、“撤回”等需要立即获得操作结果的场景。
| 对比维度 | REST (HTTP/JSON) | gRPC (HTTP/2 + Protobuf) |
|---|---|---|
| 数据格式 | JSON(文本,可读性强) | Protobuf(二进制,体积小) |
| 性能 | 中等,序列化/反序列化开销大 | 高,二进制传输 + HTTP/2 多路复用 |
| 契约定义 | OpenAPI / Swagger(文档驱动) | .proto 文件(代码生成,强类型) |
| 浏览器支持 | 原生支持 | 需 gRPC-Web 网关 |
| 流式通信 | SSE / WebSocket(非标准) | 原生支持 Server/Client/Bidirectional 流 |
| 生态成熟度 | 极高,工具链丰富 | 高,云原生首选(K8s/Istio) |
| 审批流适用场景 | 外部 API、前端直连、轻量查询 | 内部服务间高频调用、批量状态同步 |
选型建议:如果团队对 Protobuf 不熟悉,或需要对外暴露 API,优先选择 REST。如果内部服务间调用频繁、对延迟敏感(如审批节点路由计算),gRPC 能带来 30%-50% 的性能提升。
4.2 异步消息:Kafka vs RabbitMQ
异步消息适用于解耦、削峰填谷、最终一致性场景。在审批流中,常用于“审批完成通知下游”、“流程状态变更事件广播”、“超时自动处理”等非实时或需要可靠投递的场景。
| 对比维度 | RabbitMQ | Apache Kafka |
|---|---|---|
| 消息模型 | Exchange + Queue(路由灵活) | Topic + Partition(分区并行) |
| 吞吐量 | 万级/秒 | 百万级/秒 |
| 消息顺序 | 单队列内有序 | 分区内有序,全局无序 |
| 消息持久化 | 支持,但重负载下性能下降 | 磁盘顺序写,天生持久化 |
| 消息回溯 | 不支持(消费后删除) | 支持(基于 Offset 重放) |
| 运维复杂度 | 中等,Erlang 虚拟机 | 较高,需 Zookeeper/KRaft |
| 审批流适用场景 | 工作流引擎内部任务分发、延迟队列 | 审批事件总线、审计日志、大数据分析 |
避坑提示:不要将 Kafka 当作传统消息队列使用。Kafka 的设计目标是“日志存储 + 流处理”,而非“点对点即时消费”。如果业务需要精确路由、死信队列、即时重试,RabbitMQ 更合适。
4.3 同步 vs 异步:决策矩阵
以下矩阵帮助你在审批流模块间快速做出选择:
| 业务特征 | 推荐方式 | 理由 |
|---|---|---|
| 用户发起审批,需要立即知道结果 | 同步(REST/gRPC) | 用户体验要求低延迟、强一致性 |
| 审批完成后,通知多个下游系统 | 异步(Kafka) | 解耦发送方与接收方,支持广播 |
| 审批超时自动处理(延迟任务) | 异步(RabbitMQ 死信队列) | TTL + DLQ 天然支持延迟消息 |
| 审批状态变更需要记录审计日志 | 异步(Kafka) | 高吞吐、持久化、可回溯 |
| 审批节点间流转(A→B→C) | 同步(gRPC) | 流程引擎需要确认每个节点完成 |
| 批量审批数据同步到数据仓库 | 异步(Kafka Connect) | 流式 ETL,不阻塞业务 |
4.4 混合架构:CQRS + 事件驱动
企业级审批流通常采用混合通信模式:命令侧(Command)使用同步调用保证强一致性,查询侧(Query)和事件侧(Event)使用异步消息实现最终一致性和可扩展性。
4.5 选型决策流程
- 判断业务是否需要实时响应:用户等待结果 → 同步;后台处理 → 异步。
- 判断数据一致性要求:强一致性 → 同步 + 分布式事务(尽量规避);最终一致性 → 异步 + 补偿机制。
- 判断下游消费者数量:1-2 个 → 同步或 RabbitMQ;3+ 个 → Kafka 事件广播。
- 判断消息是否需回溯:审计、重放需求 → Kafka;即时消费、无需回溯 → RabbitMQ。
- 判断团队技术栈:Java/Go 生态 → gRPC 优先;多语言/前端直连 → REST 优先。
最佳实践:在审批流中,将“命令”与“事件”分离。例如:
SubmitApproval 使用 gRPC 同步调用,返回审批单 ID;审批完成后,发布 ApprovalCompletedEvent 到 Kafka,由通知服务、审计服务、数据同步服务异步消费。这种模式既保证了核心链路的高效,又实现了非核心链路的解耦。