Day33-07|14.3.2 云原生微服务:从服务拆分到全生命周期治理
Day33-07|14.3.2 云原生微服务:从服务拆分到全生命周期治理
一、教材定位与学习目标
14.3.2“云原生微服务”是云原生技术体系中的重点内容。微服务的核心不只是把一个应用拆成多个进程,而是以业务能力为边界,使服务能够独立开发、测试、部署、扩展和运行治理。云原生环境进一步要求这些服务适应动态实例、网络不可靠、自动调度、频繁发布和弹性资源。
高级系统架构设计师考试中的微服务题,通常不会只问定义,而会给出服务数量、调用链、数据库、发布方式和故障现象,让考生分析问题并给出完整方案。本篇围绕“边界、通信、数据、治理、交付、可靠性、安全”七个方面展开。
二、云原生微服务的定义
云原生微服务是面向云环境,以业务能力为边界组织的、可独立交付和运行的服务单元,并通过平台化能力实现服务发现、配置、流量治理、弹性、可观测和安全管理。
这个定义有四层含义:
- 业务边界:服务围绕业务职责,而不是围绕数据库表或代码包。
- 独立交付:服务拥有独立构建、测试、发布和回滚能力。
- 独立运行:服务可以按照自身负载和可靠性要求扩展或恢复。
- 统一治理:服务虽然自治,但必须遵循认证、审计、监控、契约和资源规范。
独立不等于完全没有依赖。服务可能依赖其他服务、数据库、消息和平台,但依赖关系必须显式、可观测、可控制,并且不能使所有服务退化为一个隐形单体。
三、服务边界设计
3.1 按业务能力划分
订单服务负责订单生命周期,库存服务负责库存可用量和变动流水,支付服务负责支付单和支付状态,会员服务负责用户身份和会员信息。每个服务应对自己的核心业务规则和数据负责。
服务边界可以依据领域模型、业务流程、变化频率、团队职责和故障隔离需求确定。边界不是永久不变的,早期可以采用模块化单体,随着业务理解成熟再逐步拆分。
3.2 数据所有权
服务拥有数据意味着它负责数据结构、写入规则、访问接口、迁移和质量,而不是简单地占有一张表。其他服务需要数据时,应通过 API、查询接口或领域事件获取,避免直接修改对方数据。
| 服务 | 自有数据 | 对外提供 |
|---|---|---|
| 订单 | 订单、明细、订单状态 | 订单查询、状态事件 |
| 库存 | 库存数量、预占记录、流水 | 可用库存、预占和释放接口 |
| 支付 | 支付单、回调和支付状态 | 创建支付、支付结果事件 |
| 会员 | 用户、地址和会员等级 | 身份和会员信息接口 |
3.3 避免分布式单体
如果多个服务必须同步同时发布、共享内部对象、共同修改表或每个请求都需要调用全部服务,说明只是形成了分布式单体。拆分后要重新设计契约、状态和一致性,不能把进程内耦合原封不动搬到网络上。
四、微服务通信模式
4.1 同步通信
HTTP、RPC 等同步方式适合需要立即得到结果的场景,例如查询商品、校验权限和读取订单。同步调用简单直观,但引入网络延迟和部分失败,必须设置超时、重试、熔断和降级。
同步调用应控制链路长度,核心请求不应无条件等待非核心服务。调用方要明确错误语义:是临时失败、业务拒绝、权限不足还是参数错误,不同类型不能使用同一种重试逻辑。
4.2 异步通信
消息队列和事件总线适合通知、积分、报表、搜索索引和设备数据等异步流程。生产者发布事实,消费者独立处理,能够削峰和解耦。异步流程需要考虑消息持久化、重复、乱序、延迟、积压、重试、死信和补偿。
4.3 API 网关
网关可以提供统一入口、认证、路由、限流、协议转换、聚合和审计。它不应成为所有业务逻辑和跨服务事务的集中地,否则会形成新的单体瓶颈。复杂聚合可以由面向特定客户端的后端聚合层承担,核心业务规则仍由领域服务负责。
4.4 服务发现
由于实例会扩缩、迁移和替换,调用方不能依赖固定 IP。服务发现维护服务名、实例地址、端口、健康状态和版本信息,配合负载均衡选择可用实例。发现缓存需要考虑过期,服务下线要尽量优雅,避免请求继续流向已停止实例。
五、服务治理能力
5.1 配置管理
配置应与镜像和代码分离,并进行版本管理、权限控制和变更审计。环境差异通过配置注入,敏感信息通过密钥管理服务引用,不能把密码、令牌和证书直接写入镜像。动态配置变更要考虑生效范围、回滚和兼容性。
5.2 流量治理
限流控制进入服务的请求量,熔断保护故障依赖,隔离避免一个依赖耗尽全部线程,重试处理临时错误,超时限制等待时间。流量治理应按租户、接口、优先级和业务重要性制定策略,不能只使用一个全局阈值。
5.3 版本治理
服务发布后可能与旧版本同时运行,接口和消息必须保持兼容。字段新增通常应向后兼容,字段删除需要过渡期;数据库变更可以采用先扩展、再迁移、后收缩的步骤;事件版本要明确消费者升级策略。
5.4 资源治理
服务要设置 CPU、内存、连接池、线程池和队列边界,避免资源无限增长。平台可以根据请求数、延迟、队列长度或业务指标弹性扩缩,但必须设置最小最大值和冷却时间。资源配额、优先级和成本标签有助于多团队共享集群。
六、微服务数据一致性
6.1 本地事务优先
服务内部的数据修改尽量在一个本地事务内完成,缩小事务边界。例如订单服务可以在本地事务中保存订单和明细,库存服务在自己的事务中保存预占记录和库存流水。跨服务强行使用分布式事务会增加锁和可用性成本,应谨慎使用。
6.2 最终一致性
订单创建后,通过可靠事件通知库存、积分和通知服务,消费者处理后更新各自状态。此时系统不是所有数据瞬间一致,而是在消息可靠、消费者可恢复和补偿机制有效的条件下最终达到一致。业务界面应能表达处理中、失败待补偿等状态。
6.3 幂等与补偿
每个业务事件应有唯一编号,消费者处理前检查处理记录;写操作使用业务幂等键和唯一约束;失败消息采用延迟重试和死信;定时补偿扫描未完成状态;对账机制检查外部支付和内部订单差异。幂等、重试、补偿和对账共同组成一致性保障,而不是单靠某一个机制。
七、微服务可靠性设计
7.1 超时和截止时间
远程调用应有连接、读取和整体截止时间。下游超时后,上游不能继续无限等待;链路中要传递剩余时间,避免下游在请求已经失效后仍继续消耗资源。
7.2 重试与熔断
只有可恢复的网络错误、临时过载等情况适合有限重试;业务拒绝、权限错误和参数错误应快速失败。指数退避和随机抖动减少并发重试;当失败率超过阈值时熔断,恢复后采用半开探测。写请求重试必须具备幂等。
7.3 隔离与降级
为不同依赖分配独立线程池、连接池或并发配额,避免推荐、报表等非核心依赖拖垮订单服务。降级要围绕业务优先级设计:可以暂时关闭推荐、延迟通知或返回缓存,但不能在没有库存确认时承诺交易成功。
7.4 健康检查与优雅退出
就绪检查决定实例是否接收流量,存活检查决定是否重启,启动检查保护启动较慢的服务。服务停止时应先摘除流量,完成正在处理的请求或把任务重新放回队列,再关闭连接。错误的健康检查和强制终止会造成请求丢失和重启风暴。
八、可观测性与运维
微服务必须输出统一的指标、日志和追踪。指标关注速率、错误率、延迟分位数、实例数、资源和队列;日志记录结构化事件、错误码、业务单号和版本;追踪记录跨服务调用和依赖耗时。请求标识和业务标识应贯穿链路。
除了技术指标,还要建立业务指标。订单系统应关注下单成功率、支付完成率和取消率;物流系统应关注轨迹延迟和异常件比例。告警需要有责任人、等级、处理手册和升级机制,不能仅把大量原始数据堆在监控平台。
九、微服务安全
服务之间不能因为处于内网就默认可信。应建立服务身份、双向认证或等效控制,并通过授权策略限制服务能访问的接口和数据。网关负责入口认证,服务内部仍需进行授权和业务校验。
密钥、证书和令牌要集中管理和轮换;镜像和依赖需要扫描;管理接口与业务接口分离;租户数据需要隔离;审计记录应包含主体、动作、资源、时间、来源和结果。安全策略要融入开发、构建、部署和运行过程。
十、微服务交付与演进
每个服务应有独立流水线,但共性步骤可以由平台模板提供。流水线包括构建、测试、契约验证、镜像扫描、部署、灰度、指标观察和回滚。数据库变更要与服务版本兼容,消息消费者要能处理旧版本事件。
服务拆分应分阶段进行:先梳理领域和模块边界,再隔离数据访问,建立接口或事件,最后迁移流量并观察。可以采用绞杀者模式逐步替换旧模块,避免一次性重写导致风险集中。每次拆分都要有回退路径和成功判定。
十一、案例分析:电商微服务的治理设计
某电商系统拆分后包含用户、商品、订单、库存、支付和通知服务。大促期间订单接口延迟暴涨,库存服务偶发超时,支付回调重复,通知积压。分析时应指出:订单同步调用链过长,库存超时可能占用订单资源;支付回调没有幂等;通知不应阻塞交易;服务治理和消息补偿不完整。
改进方案包括:订单核心流程只同步完成价格、库存预占和必要状态写入,其余通过可靠事件异步处理;库存接口设置截止时间、有限重试、熔断和隔离,并以订单号建立预占幂等;支付回调以支付流水号去重、验签和核对金额;通知使用持久化消息、重试和死信;商品查询增加缓存和独立扩展;入口设置分级限流;通过指标、日志和追踪定位具体瓶颈;发布时采用灰度和自动回滚。
方案还要考虑数据所有权:订单服务不能直接改库存表,库存服务负责库存流水;支付服务负责支付状态,订单通过事件获得结果。这样才能在保证核心业务可控的同时,让各服务独立演进。
十二、课后练习
练习一:选择题
下列哪项最符合微服务的数据自治原则?
A. 所有服务共享数据库并直接修改任意表
B. 每个服务负责自己的数据,通过接口或事件提供访问
C. 所有数据复制到每个服务中,不需要同步
D. 服务之间通过共享内存传递状态
答案:B。 数据自治要求明确所有权和访问边界,不代表必须每个服务使用独立物理数据库,但应避免任意直接修改他方数据。
练习二:简答题
微服务为什么必须具备可观测性?
参考答案: 微服务请求跨越多个进程和网络,实例动态变化,单个日志或机器指标无法解释端到端问题。通过指标、结构化日志和分布式追踪,可以定位错误率、延迟、调用路径、版本和依赖影响;结合业务指标,还能判断用户是否真正受影响,为弹性、灰度、回滚和故障恢复提供依据。
练习三:案例题
某系统把支付拆成独立服务,但订单服务仍直接查询支付数据库,支付服务升级数据库字段后订单查询失败。请分析并改进。
参考答案: 订单服务越过支付服务接口直接访问其数据库,数据库结构成为隐含公共契约,违反数据所有权和接口隔离原则。应由支付服务负责支付数据和状态,通过稳定 API 或支付结果事件向订单提供能力;接口定义版本和错误语义,数据库变更采用兼容迁移;支付回调和结果事件使用幂等键,订单服务通过状态机处理处理中、成功和失败;短期迁移期间可提供兼容视图或适配层,最终撤销直接数据库访问。改造后用契约测试、版本升级和故障演练验证兼容性。
十三、论文写作素材
论文写“云原生微服务设计”时,可以围绕服务边界、通信和可靠性三条主线展开。服务边界部分写业务能力、数据所有权和团队职责;通信部分写同步调用的超时熔断、异步消息的幂等重试和死信;可靠性部分写限流、隔离、降级、状态机、补偿和观测。
不要把微服务收益写成绝对结论。应说明服务化提高了独立发布和扩展能力,同时增加网络、数据一致性和运维复杂度;项目通过统一平台、契约治理、自动化流水线和可观测性控制了这些代价。论文结尾用实际指标说明效果,形成闭环。
十四、今日复盘清单
- 我能否从业务能力而不是数据库表划分服务?
- 我能否说明同步通信和异步通信的适用边界?
- 我能否写出服务发现、配置、流量、版本和资源治理措施?
- 我能否用本地事务、事件、幂等、补偿和对账解释最终一致性?
- 我能否分析微服务增加的复杂度,并给出验证方法?
本节的核心结论是:云原生微服务的真正难点不在拆分,而在拆分之后如何保持边界清晰、通信可控、数据一致、故障隔离、版本兼容、可观测和安全治理。只有把独立交付与统一治理结合起来,微服务才能成为可持续演进的架构,而不是分布式单体。