微服务架构的核心难点往往不在于技术选型,而在于如何科学地进行拆分。很多团队在拆分过程中发现,服务数量增加了,但系统却变得更混乱、更难以维护。问题的关键在于,拆得太细会带来运维成本爆炸式增长;而拆得太粗,则又回到了单体架构耦合的老路上。
基于大量架构设计的实践经验,我们可以将微服务的拆分策略系统性地归纳为两大核心维度:业务维度与质量维度,并配以一套务实的落地实施策略。
一、 按业务维度拆分(纵向拆分)
这是最直观、也是最常见的拆分方式,其核心在于厘清清晰的业务边界。
1、 关于 DDD(领域驱动设计)的务实态度
在具体落地时,我们常常发现 DDD 并不完全适合直接照搬。尽管 DDD 提供了卓越的理论框架和领域建模思想,但在工程实践中,如果完全教条化地遵循,可能会导致设计过度复杂,反而不利于快速迭代。
建议是:充分借鉴 DDD 中“限界上下文”(Bounded Context)的核心思想作为划分服务边界的指导原则。但在具体实施层面,必须结合团队当前的人力配置和认知水平,采取一种更灵活、务实的态度,不必追求理论上完美无瑕的领域模型。
2、 如何划定业务边界
边界的划定是拆分能否成功的关键,这一步绝不能只靠技术人员闭门造车。
- 引入业务专家参与:纯技术视角的拆分很容易失败。必须有深度理解业务的专家全程参与,共同识别哪些功能是天生紧密耦合的,哪些是相对独立、松散的。这需要结合对系统架构设计的理解,才能做出更合理的决策。
- 先粗分后演进:切忌追求一步到位、完美拆分。在项目初期,可以按照大的业务模块进行“粗粒度”拆分。随着业务不断发展,当你发现某个微服务体积变得过于庞大、职责开始模糊时,再针对性地进行二次或多次拆分。
- 参考遗留系统的实现:如果是对现有单体或巨石应用进行重构,那么旧系统中各模块间的交互频率、数据依赖关系就是宝贵的“矿藏”。仔细分析这些历史痕迹,往往能发现那些隐含的、符合实际运行规律的业务边界。
3、 服务与领域的映射关系(三个火枪手原则)
在将抽象的“领域模型”转化为物理的“微服务”时,通常会遇到以下三种映射模式:
- 领域 1 对 1 服务:这是最理想的状态。一个领域模型严格对应一个微服务,职责高度单一,边界异常清晰,便于独立开发、部署和扩展。
- 领域 多 对 1 服务:在项目初期或业务相对简单的场景下,可以将几个关联性极强的领域模型合并,部署在同一个微服务中。这样做的主要目的是降低初期的运维和部署复杂度,快速启动。
- 领域 1 对 多 服务:针对某些极其复杂的巨型领域(例如电商系统中的“订单”领域),可能出于性能、迭代速度或团队规模的考虑,需要进一步拆分为“订单创建”、“订单查询”、“历史订单归档”等多个独立的微服务,以应对不同的读写压力和变更频率。
二、 按质量维度拆分(横向/非功能拆分)
仅按业务逻辑拆分往往是不够的。一个健壮的系统还必须考虑非功能性需求(NFR),这就是按质量维度进行拆分。这种拆分通常用于解决系统的性能短板或稳定性瓶颈。
1、 按性能要求拆分
不同的业务逻辑对服务器资源(如CPU、内存、I/O)的消耗模式截然不同。
- CPU/内存密集型服务分离:例如,将“报表生成”、“图像/视频处理”这类高CPU或内存消耗的后台任务服务,与“用户登录鉴权”、“商品信息浏览”这类高并发但计算量轻的在线服务物理拆分开。
- 原因:核心在于防止后台繁重的计算任务耗尽服务器资源,从而导致前台面向用户的在线服务响应变慢甚至不可用,影响用户体验。
2、 按业务重要程度拆分
必须确保核心业务链路的稳定性,不受非核心业务波动的影响。
- 核心与非核心业务隔离:例如,“交易支付”、“库存扣减”是绝对的核心业务,而“用户评价系统”、“促销广告推送”则属于非核心或辅助业务。
- 原因:当非核心服务因流量激增、代码缺陷或外部依赖故障而崩溃时,通过物理隔离和熔断机制,可以确保其不会拖垮整个核心业务链路,保障基本业务功能的可用性。
3、 按可用性要求拆分
不同服务对可用性的承诺等级(SLA)可能不同。
- SLA 分级部署:将对可用性要求达到99.99%的服务(如API网关、统一鉴权中心)和要求为99.9%的服务(如内部运营后台、数据分析平台)分开部署和管理。高可用性服务通常需要更多的冗余副本、更精细的监控告警以及更严格的发布与回滚流程。
4、 按稳定性要求拆分
将变化频率不同的代码分离开,以保护核心稳定部分。
- 动静分离:将“长期保持稳定、很少变更的基础功能或核心算法”与“频繁迭代、响应业务需求变化的业务逻辑代码”进行拆分。
- 原因:避免因为频繁修改边缘业务代码,不小心引入错误,从而导致原本运行稳定、肩负重任的核心基础功能发生崩溃。这种拆分直接提升了整个系统架构的韧性与可维护性。
三、 整体落地思路
掌握了拆分的理论维度后,如何将其转化为具体的行动方案呢?
1、 拆分方式的组合拳
在实际操作中,按业务拆分和按质量拆分绝非互斥,而是需要协同进行的“组合拳”。通常的路径是:首先按照业务维度梳理出主要的服务板块;随后,在运行过程中,针对暴露出的性能瓶颈、稳定性问题或核心链路,再进行质量维度的针对性细拆和优化。
2、 基础设施的准备
微服务不仅是代码的拆分,更是对团队基础设施能力的全面考验。基础设施必须先行,至少要与服务拆分同步进行。
- 构建最简核心基础设施:不需要一开始就搭建一个像大厂那样面面俱到的完美平台。但必须确保具备最核心的支撑能力:自动化部署(CI/CD)、服务注册与发现、基础指标监控、分布式链路追踪。这四项是微服务可运维的基石。
- 逐步完善高级能力:随着服务数量的增长和业务复杂度的提升,再逐步引入和建设熔断降级、配置中心、API网关、混沌工程等更高级的基础设施能力。
3、 落地方式:拒绝“大爆炸”
- 逐步迭代(强烈推荐):采用经典的“绞杀者模式”。保持旧有单体系统正常运行,所有新功能都在新的微服务中开发和上线。同时,有计划地将旧系统中的功能模块逐一剥离、重构并迁移到微服务中,最终“绞杀”掉旧系统。这种方式业务风险最小,支持持续交付。
- 避免一步到位的重写:停止一切业务开发,集中全部人力,试图在几个月内将整个庞大系统一次性重写为微服务架构。这种“大爆炸”式的改革在历史上成功率极低,往往因周期过长、业务变化、团队疲惫而烂尾。
总结
微服务拆分没有放之四海而皆准的“银弹”,它本质上是一种权衡的艺术,是在 “开发效率”、 “运维复杂度” 和 “系统性能与稳定性” 之间寻找最佳平衡点。
- 初期:应优先关注业务边界的梳理,秉持“宁粗勿细”的原则,控制微服务数量,降低起步阶段的复杂度。
- 中期:随着业务发展和系统压力显现,开始重点关注性能瓶颈和稳定性问题,运用质量维度进行针对性的拆分和优化。
- 全程:必须坚持“基础设施先行”的原则,并采用“小步快跑、持续验证”的迭代策略,避免任何形式的“大跃进”。
希望这份结合了业务与质量双维度的拆分指南,能帮助你在微服务架构的实践中少走弯路。更多关于分布式系统、架构设计及 DevOps 实践的深度讨论,欢迎访问 云栈社区 与广大开发者共同交流成长。
|