28.1 SOA
一句话
SOA 不是 “服务很多”,而是 “用可复用的服务契约去组合业务流程”:每个服务暴露粗粒度、业务语义完整的接口,由编排层组合;它的成败不在技术,而在企业级契约治理能否长期维持。
SOA 与微服务的差别
| 维度 | SOA | 微服务 |
|---|---|---|
| 服务粒度 | 粗(业务能力级,如“客户管理”) | 细(一个限界上下文) |
| 通信 | 企业服务总线(SOAP/WSDL、MQ) | HTTP/gRPC + 事件 |
| 治理 | 集中(注册表、契约库、ESB) | 分散(每个团队自治) |
| 数据 | 常共享企业级数据库 | 每服务独立数据 |
| 组织前提 | 企业级架构委员会 | 小团队 + 平台能力 |
| 典型失败 | 总线变成逻辑黑洞 | 分布式单体 |
一句话判据:SOA 假设 “企业能统一治理”,微服务假设 “团队能自治”;组织形态不同,硬套都会失败。
代码:一个 SOA 契约的样子
<!-- 粗粒度、以业务动词命名,入参出参都是业务文档 -->
<wsdl:portType name="CustomerService">
<wsdl:operation name="MergeCustomer">
<wsdl:input message="tns:MergeCustomerRequest"/> <!-- 源客户、目标客户、操作人 -->
<wsdl:output message="tns:MergeCustomerResponse"/> <!-- 合并结果、受影响订单数 -->
</wsdl:operation>
</wsdl:portType>
对比微服务的细粒度:GET /customers/{id}、PATCH /customers/{id}——SOA 倾向于 一次调用完成一个业务动作,减少跨服务往返。
实测:粗粒度与细粒度差多少次调用
按 “一次下单要经过 校验/库存/价格/优惠/风控/支付/通知” 的流程做算术(不是跑代码,是可验算的计数):
| 风格 | 调用次数 | 说明 |
|---|---|---|
| 细粒度(每步一个 RPC) | 7–12 次 | 每次 1 RTT,同城 1ms → 7–12ms,跨城 ×3 |
| 粗粒度(一个业务动作一次调用) | 1 次 | 服务端内部完成多步,客户端只等一个结果 |
推论:同城 1ms、跨城 30ms 时,细粒度编排的往返成本会从 7ms 变成 200ms+——这就是 SOA 强调 “粗粒度、业务语义完整” 的量化理由。SOA 的复用单位是 “业务动作”,不是 “数据操作”。
反模式
| 反模式 | 后果 |
|---|---|
| 把 ESB 当“业务逻辑容器” | 逻辑沉淀在中间件,无法版本化(见 28.2 ESB) |
| 服务粒度按“技术层”切(用户服务/订单服务/...) | 一次业务变更要改多个服务,退化成分布式单体 |
| 契约不做版本管理 | 调用方被动升级,集成事故频发 |
| 共享企业级数据库 | 服务独立演进失败 |
| 只做“服务化”不做“治理” | 服务数量上去,复用率仍为零 |
| 用 SOA 解决“组织问题” | 技术层解不了部门墙 |
| 用“服务多”冒充服务化 | 等于把单体拆成分布式调用,复用率为零 | | 契约库没有 owner | 服务被复用了却没人敢改,最终废弃 |
三条铁律
🔑 SOA 的收益来自 “复用 + 契约治理”,不来自 “拆服务”。
🔑 契约要粗粒度、业务语义完整;细碎接口会把耦合推给调用方。
🔑 治理必须集中、技术可以分散;契约库/版本策略是它的生命线。
自检
Q1 “我们把单体拆成了 20 个服务,所以做了 SOA”——这句话错在哪?
▸ 答案:错在把 SOA 等同于拆服务。SOA 的核心是 “可复用的业务服务 + 契约治理”:如果 20 个服务仍然各自读同一张表、接口按技术而非业务切、契约没有版本,那只是 “分布式单体”,既没有复用也没有治理。
Q2 为什么 SOA 倾向粗粒度接口?
▸ 答案:因为它的目标是 业务复用与流程组合:粗粒度接口(“合并客户”)把一次业务动作封装在一个调用里,编排层只需组合少量服务;细粒度接口会让调用方承担编排与一致性责任,跨网络往返也更多。
Q3 SOA 与 “中台” 是什么关系?
▸ 答案:中台可以看作 “SOA 思想的一种组织化落地”:把可复用的业务能力沉淀为共享服务,由业务方组合。成败同样取决于契约治理与 owner 机制——没有 owner 的 “共享服务” 会变成谁都不敢改的遗留系统。
Q4 什么情况下不该选 SOA?
▸ 答案:团队小(< 10 人)、业务边界还在快速变化、没有企业级治理能力时。此时粗粒度服务会成为 “改一处要协调三方” 的负担;模块化单体(见 27.2 模块化单体)更划算。
Q5 SOA 的服务注册中心今天还有用吗?
▸ 答案:有,但形态变了:从 “UDDI 式静态注册表” 变成 “服务发现 + 契约仓库 + API 目录”。核心价值仍是 可发现、可追溯的契约,而不是 “注册表技术” 本身。
Q6 为什么说 “SOA 的失败通常是组织失败”?
▸ 答案:因为服务复用要求 跨部门的契约承诺:谁维护、谁升级、谁兜底。没有跨部门治理机制时,服务要么没人复用(重复建设),要么被复用后不敢改(僵化)。技术选型再对,也救不了这两件事。
Q7 粗粒度接口会不会变成 “上帝服务”?
▸ 答案:会,如果它把 “不该在一个事务里的步骤” 强行合并。判据是事务边界与变更频率:同属一个业务动作、必须一起成功/失败的步骤可以合并(下单+锁库存);只是流程相邻、但可以独立失败的步骤(通知、积分)应拆出去用事件。粗粒度 ≠ 大泥球,关键在边界是否对齐业务不变量。
故障复盘(典型模式,脱敏)
| 阶段 | 现象 | 判断 | 动作 |
|---|---|---|---|
| 上线 6 月 | 12 个 “可复用服务”,实际只有 1 个被 2 个系统调用 | 契约无 owner、无文档 | 建契约库 |
| 第 7 月 | 唯一被复用的服务要改字段,调用方拒绝升级 | 无版本策略 | 加 v2 + 双跑 |
| 第 9 月 | 团队开始各自复制服务 | 复用收益为负 | 重新定义粒度 |
根因:只做了 “服务化”,没做 “契约治理”。代价:重复建设 + 复用车成本高于自建。根治:契约库 + 版本策略 + 明确 owner,否则别谈复用。