ARTICLE · 1150270
第25讲:软件服务设计
用户服务:负责用户注册、身份资料和账户状态管理。 商品服务:负责商品信息、价格展示和库存查询。 订单服务:负责订单创建、订单状态和订单生命周期管理。 支付服务:负责支付请求、支付结果处理和退款。 物流服务:负责配送单生成、物流状态查询和配送跟踪。 通知服务:负责发送电子邮件、短信或应用内消息。
接口地址、操作名称和请求方法。 请求参数、数据类型与校验规则。 响应结构、错误码和异常语义。 身份认证、授权和数据访问约束。 超时、重试、幂等性及版本兼容要求。 服务质量要求,例如延迟、可用性和吞吐量。 契约不仅是接口文档,也是服务协作的基础。
概念 | 核心含义 | 与服务的关系 |
函数或方法 | 执行一段计算或操作 | 可以是服务内部的实现单元 |
模块 | 按职责组织代码与数据 | 可以包含一个或多个服务 |
软件组件 | 具有相对明确接口的可复用软件单元 | 组件可以实现服务,也可以依赖服务 |
API | 调用软件能力的接口集合 | 是服务对外暴露能力的一种方式 |
软件服务 | 通过契约提供明确能力的逻辑单元 | 本章讨论的核心对象 |
微服务 | 面向特定业务能力、可独立部署和演进的服务架构单元 | 是服务的一种架构组织方式 |
Web 服务 | 通常通过 Web 协议进行交互的软件服务 | 是软件服务的常见实现形式 |

设计什么服务?应当识别哪些独立的业务能力? 服务负责什么?每个服务的职责边界和业务规则是什么? 服务如何协作?服务之间通过同步调用、异步消息还是事件进行交互? 服务如何被使用?如何定义接口、数据格式、错误语义与安全约束? 服务如何运行?如何满足性能、可用性、可靠性和可观测性要求? 服务如何演进?如何支持业务变化、接口升级和系统迁移?

设计活动 | 主要关注点 | 典型产出 |
需求分析 | 用户需要什么能力 | 用例、需求规格、业务规则 |
软件架构设计 | 系统整体如何组织 | 架构视图、组件关系、部署结构 |
服务设计 | 服务如何划分、协作与演进 | 服务目录、边界说明、接口契约 |
API 设计 | 外部调用者如何使用接口 | OpenAPI 文档、请求与响应模型 |
详细设计 | 服务内部如何实现 | 类图、算法、模块设计 |
运维设计 | 服务如何稳定运行 | 监控指标、告警、容灾和恢复方案 |
职责过多的服务:一个服务承担用户、订单、支付、库存等大量无关职责。 过度细分的服务:一个简单业务操作被拆成多个极小服务,导致每次请求都需要频繁跨网络调用。
性能:响应时间、吞吐量和资源消耗。 可靠性:故障隔离、重试、超时与恢复能力。 可扩展性:负载增长时的扩容能力。 安全性:认证、授权、数据保护和审计。 可维护性:代码理解、测试和修改成本。 可观测性:日志、指标、分布式追踪和告警。 可演进性:契约兼容、版本管理和渐进式迁移。
商品目录中的标价。 营销活动中的促销价格。 订单创建时采用的成交价格。 财务系统中的结算金额。
该业务能力是否具有明确、独立的业务目的? 相关规则是否需要共同维护? 哪些数据应由该服务负责写入和维护? 这些功能是否需要一起变更和发布? 将它们拆开后,是否会产生大量网络调用或跨服务事务? 该边界是否符合团队的职责划分和运维能力?
POST /orders:创建一个新订单。 POST /orders/{id}/cancel:请求取消订单。 GET /orders/{id}:查询订单详情。
层次 | 需要明确的内容 |
语法契约 | 字段、类型、格式、必填项 |
业务契约 | 前置条件、业务规则、状态变化、结果含义 |
运行契约 | 超时、限流、重试、幂等性和可用性 |
安全契约 | 身份认证、访问权限、敏感数据处理和审计 |
谁是某项业务数据的权威维护者? 其他服务通过什么方式获取或订阅这些数据? 数据变化如何在多个服务之间保持业务一致性?
共享数据库表:多个服务直接读写同一组业务表。实现方便,但容易造成结构耦合与发布协调。 服务拥有数据:每个服务控制自己的数据修改,通过契约提供外部访问。边界更清晰,但跨服务查询和一致性处理更复杂。 复制或投影数据:通过事件或同步机制,在其他服务维护查询所需的数据副本。可以降低实时调用依赖,但必须处理延迟、重复消息和数据重建。

调用超时和取消机制。 失败重试与退避策略。 幂等性和重复消息处理。 服务发现与负载均衡。 调用链中的身份和权限传递。 事件顺序、重复投递及最终一致性。 故障隔离与降级策略。
服务目录与接口文档管理。 服务所有者和维护责任登记。 API 版本和兼容性策略。 身份认证与权限管理。 依赖关系、变更风险和弃用管理。 统一的监控、告警与审计规范。 服务质量目标和运行成本管理。

用户如何选择商品和提交订单? 系统如何校验商品价格与库存? 订单在什么情况下可以取消? 支付失败后,订单和库存应当如何处理? 用户重复提交请求时,系统应当如何响应? 系统需要满足什么样的响应时间、并发量和可用性目标?
业务动作 | 产生的业务结果 | 候选责任主体 |
提交订单 | 订单已创建 | 订单服务 |
预留库存 | 库存已预留 | 库存服务 |
完成扣款 | 支付成功 | 支付服务 |
确认发货 | 配送任务已建立 | 物流服务 |
订单已取消 | 订单取消状态已记录 | 订单服务 |
服务名称和业务目的。 负责的业务规则和数据。 对外提供的主要能力。 不负责的业务内容。 依赖的其他服务。 允许的调用方式和交互方向。 需要满足的关键质量属性。
商品是否存在、是否允许购买。 价格由哪个服务确定。 运费与优惠如何计算。 库存不足时返回什么结果。 相同幂等键再次提交时返回什么结果。 认证失败、参数错误和业务冲突如何区分。 响应中的金额精度和货币单位如何表达。
订单保存成功,但事件发布失败。 库存预留成功,但支付失败。 支付服务处理成功,但响应丢失。 消息被重复投递。 下游服务长时间不可用。 用户在订单处理期间重复提交请求。
高并发下库存预留是否会超卖? 支付请求超时后,系统如何判断实际支付结果? 一个下游服务失效是否会拖垮整个调用链? 服务拆分后,关键查询是否需要过多跨网络调用? 服务间的数据最终一致性能否满足业务要求? 可使用接口原型、性能测试、故障注入、契约测试和架构评审等方法验证这些问题。 评审应同时检查业务正确性和运行质量,而不仅是接口命名或代码风格。
单元测试:验证业务规则和状态转换。 接口测试:验证参数、响应、错误码和权限约束。 契约测试:验证调用方与提供方对接口的理解是否一致。 集成测试:验证服务、数据库和消息系统之间的协作。 端到端测试:验证完整业务流程。 非功能测试:验证性能、安全性、故障恢复和资源使用。
是否存在不必要的同步依赖? 是否需要聚合接口或面向前端的后端(BFF)? 是否需要构建读模型? 是否有必要调整服务边界?
服务职责过宽,形成新的“巨型服务”。 服务过细,业务操作被拆分成大量微小调用。 多个服务反复维护相同的业务规则。 一个业务需求需要同时修改多个服务。 服务之间形成循环依赖。
明确每个服务的数据所有权。 通过契约访问其他服务的数据。 使用稳定的业务标识,而不是暴露内部数据库主键规则。 通过契约测试约束接口变化。 减少循环依赖和跨服务直接写入。
方法 | 适用情况 | 主要代价 |
本地数据库事务 | 业务状态位于同一数据存储内 | 无法直接覆盖多个独立服务 |
Saga | 多个服务需要协同完成较长业务流程 | 需要补偿逻辑和流程监控 |
事务性发件箱 | 数据更新必须可靠地通知下游 | 需要事件发布和重复消费处理 |
最终一致性 | 允许不同服务的数据短时间不一致 | 需要定义延迟、重试与修复机制 |
保持单一事务边界 | 强一致性要求高且业务边界适合合并 | 可能限制独立扩展与部署 |
为远程调用设置合理超时。 只对适合重试的失败进行有限重试。 使用指数退避和随机抖动减少重试风暴。 对重复操作使用幂等机制。 在必要时使用熔断和舱壁隔离。 对非关键功能实施降级。 通过监控和追踪定位故障源。
优先进行向后兼容的增量变更。 明确字段是否必填及其默认语义。 为破坏性变更设计版本迁移方案。 通过自动化契约测试验证兼容性。 监控旧接口使用情况,制定清晰的弃用周期。·
只验证用户是否登录,却没有检查用户是否有权访问目标资源。 内部服务默认信任所有内部请求。 在日志中记录密码、令牌、支付凭据等敏感数据。 允许调用方直接修改受保护的业务状态。 服务间使用长期有效且权限过大的凭据。 缺少敏感操作审计。
支付服务是否真的处理成功? 事件是否成功发布? 消息是否被消费? 订单状态更新是否失败? 是否存在重复事件或乱序处理?·
问题 | 主要表现 | 优先改进方向 |
边界不清 | 频繁跨服务修改 | 重新进行领域分析 |
耦合过强 | 共享表、循环调用 | 明确契约与数据所有权 |
数据不一致 | 订单、库存、支付状态不匹配 | 事务边界、Saga、发件箱 |
故障传播 | 下游故障拖垮上游 | 超时、隔离、降级 |
接口不兼容 | 升级导致调用方失败 | 契约测试、渐进式迁移 |
安全不足 | 越权、敏感信息泄露 | 授权、最小权限、审计 |
监控不足 | 无法还原调用链 | 日志、指标、追踪 |
过度拆分 | 运维复杂、开发变慢 | 模块化单体、按需拆分 |
用户只能访问自己有权查看的订单。 商品价格由可信的业务服务确定,不能直接信任客户端提交的价格。 库存不足时不能确认库存预留成功。 相同请求重复提交时,不应重复创建订单或重复扣款。 支付结果可能延迟到达,订单状态需要支持异步更新。 任何失败都应有明确的业务状态和恢复方案。 系统需要记录关键状态变化,以支持追踪和审计。

接口 | 方法 | 主要作用 |
创建订单 | POST /api/v1/orders | 校验请求并发起订单流程 |
查询订单 | GET /api/v1/orders/{id} | 查询订单及其当前状态 |
取消订单 | POST /api/v1/orders/{id}/cancel | 在满足条件时取消订单 |
查询支付状态 | GET /api/v1/orders/{id}/payment | 获取与订单关联的支付状态 |
调用方的身份和权限。 商品标识、购买数量和收货地址。 服务端的价格校验与金额计算规则。 幂等键的使用范围与有效期。 创建成功与业务失败的响应语义。 订单进入待支付状态的准确含义。


故障场景 | 设计策略 |
商品无效或价格校验失败 | 拒绝创建订单并返回明确业务错误 |
库存不足 | 不确认订单进入可支付状态,返回库存不足结果 |
订单保存成功但事件未发出 | 使用事务性发件箱或可恢复的发布机制 |
支付请求超时 | 查询或核实支付状态,不直接假定支付失败 |
支付成功但通知延迟 | 保持处理中状态,等待事件或主动对账 |
取消订单时库存已预留 | 释放相应库存,并记录补偿结果 |
重复收到支付成功事件 | 使用事件标识和业务状态校验,避免重复处理 |
python
from dataclasses import dataclassfrom decimal import Decimalfrom enum import EnumclassOrderStatus(str, Enum):PENDING_PAYMENT="PENDING_PAYMENT"PAID="PAID"CANCELLED="CANCELLED"@dataclassclassOrder: order_id: str user_id: str total_amount: Decimal status: OrderStatusdefcreate_order( user_id: str, items: list[dict], idempotency_key: str, product_service, order_repository,) -> Order:# 1. 检查请求幂等性 existing = order_repository.find_by_idempotency_key( user_id, idempotency_key )if existing isnotNone:return existing# 2. 校验商品并使用可信的服务端价格 total = Decimal("0.00")for item in items: product = product_service.get_product(item["productId"]) quantity = item["quantity"]if quantity <=0ornot product.is_available:raiseValueError("商品不可购买或数量无效") total += product.price * quantity# 3. 创建订单;生产实现还需处理并发幂等与数据库事务 order = Order(order_id=order_repository.new_id(),user_id=user_id,total_amount=total,status=OrderStatus.PENDING_PAYMENT, ) order_repository.save( order,idempotency_key=idempotency_key, )return order调用方不能直接决定订单金额。 订单状态由服务内部业务逻辑控制。 幂等性是接口行为的一部分。 商品查询通过服务接口完成,而不是直接读取商品服务的内部数据库。
交易流程的正确性。 高并发下的库存一致性。 支付与退款的状态管理。 促销规则的独立演进。 故障时的订单恢复和业务对账。
契约的可理解性和稳定性。 认证、授权和访问限制。 请求签名、幂等键和防重放。 速率限制和异常响应。 版本兼容、变更通知和弃用策略。 操作审计和调用统计。
应用场景 | 设计重点 | 主要风险 |
企业信息系统 | 业务边界、权限、数据治理 | 遗留依赖与跨部门协调 |
电商交易 | 状态机、幂等、事务一致性 | 超卖、重复扣款、状态不一致 |
云原生系统 | 部署自治、故障隔离、可观测性 | 运维复杂度与依赖传播 |
开放 API | 契约稳定、安全、兼容性 | 越权、滥用、破坏性变更 |
物联网平台 | 事件流、吞吐量、背压 | 消息积压与数据丢失 |
AI 应用 | 能力分层、权限、模型治理 | 延迟、成本与结果不可控 |
遗留系统改造 | 渐进迁移、适配与边界隔离 | 双重维护和迁移风险 |
比较维度 | 模块化单体 | SOA | 微服务 |
部署方式 | 通常统一部署 | 通常具有多个服务 | 强调独立部署与演进 |
模块边界 | 由代码结构和约束维护 | 由服务契约与集成机制维护 | 由业务边界、契约与部署边界共同维护 |
服务通信 | 主要是进程内调用 | 常见于跨系统通信 | 常见于轻量级 API 和事件通信 |
数据管理 | 可使用统一数据库 | 可集中或分布式管理 | 倾向于服务拥有自己的业务数据 |
运维复杂度 | 相对较低 | 取决于集成规模 | 通常较高 |
适用情境 | 小型系统、初期产品、边界尚在探索的业务 | 企业集成、多系统协作 | 复杂业务、独立扩展和独立发布需求明确的系统 |
按数据库表拆分服务:表的边界不一定等于业务边界。 为了使用微服务而拆分:缺少明确收益,却增加部署和运维成本。 直接暴露内部数据结构:让调用方依赖数据库模型,导致接口难以演进。 建立共享数据库写入机制:不同服务能够随意修改同一业务对象,削弱责任边界。 只设计成功路径:忽略超时、重复请求、消息丢失和补偿处理。 把所有服务调用都设计成同步请求:增加延迟,并可能形成长调用链。 过度依赖异步消息:虽然降低同步耦合,却可能使业务流程难以追踪。 把接口文档当作完整契约:只记录字段,不定义业务状态、权限和失败语义。 缺乏服务所有者:没有明确团队负责接口、运行质量和变更管理。
服务有明确的业务目的和职责范围 已明确服务负责维护的数据与业务规则 已识别跨服务依赖及不必要的循环依赖 已判断是否确实需要独立部署
请求、响应、错误语义和业务前置条件清晰 认证、授权与数据访问约束明确 已考虑接口兼容性与版本演进 写操作已定义幂等性和重复请求处理
已定义超时、重试和故障隔离策略 已考虑跨服务数据一致性和补偿机制 异步事件有明确的发布、消费与重复处理策略 关键业务状态可以查询和恢复
有日志、指标、追踪和告警方案 有单元测试、契约测试和集成测试 有安全审计与敏感数据保护措施 有服务负责人、部署和回滚方案 重置检查 复制检查结果
[1] BOOTH D, HAAS H, MCCABE F, et al. Web Services Architecture. W3C Working Group Note, 2004. 网址:https://www.w3.org/TR/2004/NOTE-ws-arch-20040211/
主要贡献:定义 Web 服务架构中的服务、请求者、提供者、服务描述与语义契约等概念,是理解服务交互和契约设计的基础文献。
[2] ERL T. SOA Principles of Service Design. Prentice Hall, 2008. 相关资料:Pearson 出版资料及书籍节选
主要贡献:系统阐述面向服务设计中的标准化契约、松耦合、服务抽象、自治、无状态性与可组合性等原则。
[3] EVANS E. Domain-Driven Design: Tackling Complexity in the Heart of Software. Addison-Wesley, 2003.
主要贡献:提出领域驱动设计的核心思想,重点讨论领域模型、通用语言、限界上下文以及复杂业务软件的建模方法。该书可通过出版社或图书馆目录检索。
[4] NEWMAN S. Building Microservices: Designing Fine-Grained Systems. 2nd ed. O’Reilly Media, 2021.
主要贡献:从服务边界、信息隐藏、耦合、团队组织和系统演进等角度讨论微服务设计与工程实践。
参考资料:Building Microservices, Second Edition
[5] ZHONG C, LI S, HUANG H, et al. Domain-Driven Design for Microservices: An Evidence-Based Investigation. IEEE Transactions on Software Engineering, 2024, 50(6): 1425–1449.
DOI:https://doi.org/10.1109/TSE.2024.3385835
主要贡献:从证据角度研究领域驱动设计在微服务中的应用,为服务边界识别的方法、收益与实际挑战提供研究依据。
[6] ÖZKAN O, BABUR Ö, VAN DEN BRAND M. Domain-Driven Design in Software Development: A Systematic Literature Review on Implementation, Challenges, and Effectiveness. 2023.
预印本:https://arxiv.org/abs/2310.01905
主要贡献:系统梳理 DDD 的实施方式、应用效果和实践挑战,适合进一步研究领域建模、限界上下文和领域事件。
二、架构设计与工程实践资料
[7] FOWLER M. Microservices. 2014.
网址:https://www.martinfowler.com/articles/microservices.html
主要贡献:讨论微服务架构的基本特征、服务边界、独立部署和演进设计。
[8] FOWLER M. Microservice Trade-Offs. 2015.
网址:https://www.martinfowler.com/articles/microservice-trade-offs.html
主要贡献:分析微服务在模块化、部署自治、分布式通信、数据一致性与运维复杂度方面的权衡。
[9] FOWLER M. Microservice Prerequisites. 2014.
网址:https://martinfowler.com/bliki/MicroservicePrerequisites.html
主要贡献:讨论采用微服务之前应具备的自动化部署、基础设施管理和持续交付能力。
[10] AMAZON WEB SERVICES. Saga Pattern. AWS Prescriptive Guidance.
网址:https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-data-persistence/saga-pattern.html
主要贡献:介绍 Saga 如何通过本地事务、流程协调和补偿操作管理跨微服务业务流程。
[11] AMAZON WEB SERVICES. Transactional Outbox Pattern. AWS Prescriptive Guidance.
网址:https://docs.aws.amazon.com/prescriptive-guidance/latest/cloud-design-patterns/transactional-outbox.html
主要贡献:解释数据库更新与消息发布之间的双写问题,以及事务性发件箱、重复消息处理和事件顺序等工程问题。
[12] WORLD INTELLECTUAL PROPERTY ORGANIZATION. CWS/13/19. 2025.
网址:https://www.wipo.int/edocs/mdocs/cws/en/cws_13/cws_13_19.pdf
主要贡献:提供 Web API 与面向服务设计原则方面的补充材料,可用于进一步了解标准化服务契约及接口治理。