十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

微服务问题:服务拆分边界模糊

微服务问题:服务拆分边界模糊 一、 这个问题到底是什么这个问题在微服务架构演进中极为典型其本质是“伪微服务”或“技术分层拆分”反模式。表面现象按技术层Controller/Service/DAO或纯包名order.service、order.dao拆分服务。深层病因贫血模型与事务脚本拆分时只关注了“代码放哪”没关注“业务边界在哪”。服务A可能只负责订单数据的“增删改查”服务B负责“状态流转”导致一个完整的“下单”业务流横跨多个服务。数据库耦合虽然服务拆开了但底层可能共用一张数据库表或者存在大量的跨库Join查询迫使你在服务A里调用服务B的接口来拼装数据。变更传导因为业务逻辑分散当产品经理提出“修改运费计算规则”时你发现订单服务、履约服务、支付服务、促销服务都得改代码——这就是你提到的“牵一发动全身”。争对这些问题我看到了三个方案分别是采用领域驱动设计DDD依据业务子域和限界上下文划分服务边界。遵循康威定律团队结构与服务架构对齐。使用扼杀者模式逐步改造遗留单体系统。二、方案一领域驱动设计DDD我们以 DDD 为指导将每个微服务视为一个独立的业务能力中心。每个服务拥有自己完整的垂直架构包含独立的 Controller、业务逻辑、Entity 和数据库对外仅通过 API 契约进行通信实现逻辑与数据的双重封装。但是这是最终目标并不是一开始就是这样的。1. 为什么需要它传统三层架构Controller-Service-DAO是“面向数据库”的。你把表映射成对象Service里写满CRUD。当业务变复杂时业务规则散落在各个Service方法里没人说得清“下单”到底包含哪些步骤、有哪些约束。改一个规则你不知道会影响到哪里。DDD的核心假设软件的核心价值是承载业务逻辑而不是增删改查。因此代码结构必须与业务模型一一对应。2. 它是什么DDD是一套建模方法论它提供了一套完整的战术和战略工具帮助你把复杂的业务领域映射到软件模型中。战略设计用子域核心/支撑/通用划分业务优先级用限界上下文划清不同业务概念的边界用上下文映射图描述服务间的关系。战术设计用实体有唯一标识、值对象不可变、无标识、聚合一组相关对象的集合通过聚合根统一访问、领域事件、领域服务等构件把业务规则落地为代码。3. 怎么做第一步事件风暴工作坊召集业务专家和技术专家用便利贴按时间线列出所有领域事件如“订单已支付”。反推触发事件的命令如“支付订单”以及命令执行所需的数据和规则。识别出聚合一组必须保持强一致性的对象和聚合根聚合的对外入口。我的理解就是画业务状态变迁图知道哪些事务应该同时成功或者失败。第二步划定限界上下文当发现同一个概念如“商品”在不同场景下含义不同时就划为不同的上下文。例如“商品”在“商品上下文”里有重量、尺寸、生产批次但在“订单上下文”里只需要名称、价格快照、SKU ID。在微服务架构中属于‘事实发生’类型的数据如下单、支付、退款必须采用‘快照模式’。即在存储业务事件时必须冗余存储当时的关键业务字段名称、价格、税率禁止仅存储外键 ID 并依赖实时 RPC 查询来拼装历史单据。我的理解就是对于不可变更的数据在存储的时候我就应该把当时的数据状态存储进去这应该是存快照的原则。给‘商品’在两个业务场景上架管理和下单交易中赋予不同的属性集合和生命周期。为了物理隔绝‘商品改名’对‘历史订单’的篡改我们强制在订单服务中建立独立的实体OrderItem并冗余存储下单时的状态快照。第三步代码结构改造抛弃controller/service/dao按限界上下文建包。每个上下文内部按interface接口层、application应用层、domain领域层、infrastructure基础设施层分层。铁律所有核心业务逻辑必须写在domain层application层只做用例编排和事务管理infrastructure层只做技术实现数据库、MQ、RPC。interface层 负责接收HTTP请求和 接收其他服务的RPC请求校验参数转发相当于之前的controller层。Application应用层负责开启事务编排流程保持事务一致性。Domain领域层写业务规则。Infrastructure基础设施层连MySQL、调Feign(发HTTP请求、调其他微服务的接口、处理网络超时)、发MQ(发消息、消费消息、处理重试)、存Redis。4. 为什么这么做因为业务复杂度是系统复杂度的主要来源。技术复杂度网络、并发、缓存是通用的但业务复杂度是独特的。DDD把精力聚焦在最难的部分——业务逻辑本身。因为“统一语言”能消除沟通歧义。开发说“订单状态”产品说“订单生命周期”两者不一致就会导致理解偏差进而导致代码偏差。DDD强制你用同一个词汇表从PRD到代码统一命名。5. 有什么原则原则一以业务为核心而非以数据为核心。原则二聚合内强一致性聚合间最终一致性。一个事务只修改一个聚合跨聚合的状态同步用领域事件异步完成。原则三限界上下文之间通过防腐层ACL隔离防止外部概念污染内部模型。三、方案二康威定律1. 为什么需要它人是架构的第一性原理。你画了再完美的服务边界图如果团队还是按“前端组/后端组/DBA组”来组织那么沟通路径一定会压倒设计意图。A团队改订单B团队改库存两边开会吵架最终为了“方便协作”又把逻辑揉在一起边界形同虚设。康威定律的核心洞见系统架构是组织沟通结构的镜像。你想得到什么样的架构就必须先建成什么样的团队。2. 它是什么康威定律是一个社会学观察由Melvin Conway在1967年提出“设计系统的组织其产生的设计等同于组织内部的沟通结构。”在微服务语境下它被演绎为“你打算怎么拆服务就先把团队怎么拆。”3. 怎么做第一步重组为“业务特性团队”解散技术职能团队组建“订单域团队”、“库存域团队”、“用户域团队”。每个团队是全功能团队包含产品经理、开发前端后端、测试、DBA、运维。团队拥有该域服务的完整所有权设计、开发、测试、部署、运维。第二步定义团队间的“契约”强制要求跨团队调用必须先定义接口OpenAPI或gRPC Proto双方签字确认后各自独立开发。接口变更必须向后兼容只加字段不改已有字段类型。不兼容的变更必须提供v2版本并给下游至少3个月迁移期。第三步独立发布线每个团队拥有独立的CI/CD流水线、独立的部署环境。团队可以独立决定发布节奏不需要等待其他团队。4. 为什么这么做因为沟通成本是系统复杂度的放大器。如果团队间需要频繁沟通才能确认接口语义那么“解耦”就是一句空话。康威定律把“频繁沟通”的范围压缩到团队内部跨团队只通过“标准化契约”通信。因为所有权感驱动质量。当团队对自己负责的服务拥有从开发到运维的全生命周期责任时他们会更谨慎地设计、更积极地监控。5. 有什么原则原则一团队自治是前提不是奖励。赋予团队完全的技术决策权和运维权。原则二接口契约是法律不是建议。任何破坏向后兼容的变更都必须走正式的版本升级流程。原则三失败自担不甩锅。如果A团队改了接口导致B团队挂了那是B团队没有及时跟进契约变更责任在B因为他们自己决定什么时候升级依赖。四、方案三扼杀者模式1. 为什么需要它因为现实中没有“绿field项目”。你的系统已经在运行有大量用户和数据不可能停机重写。传统的“大爆炸式重写”失败率超过90%因为周期太长、风险太高、业务等不起。扼杀者模式的核心思想与其“推倒重来”不如“逐步替换”。就像一棵藤蔓植物慢慢缠绕并扼杀宿主树一样新系统逐步接管旧系统的功能直到旧系统彻底死去。2. 它是什么扼杀者模式Strangler Fig Pattern是Martin Fowler提出的渐进式系统重构模式。它通过在旧系统外围逐步构建新系统并在网关层拦截和路由流量实现新旧系统的平滑过渡。3. 怎么做第一步选择“叶子”功能挑选一个边缘的、独立的、变更频繁的功能作为第一个迁移目标如“积分计算”而不是核心交易链路。这样可以快速验证流程降低风险。第二步在网关层做路由在API网关或Nginx层配置路由规则如按URL前缀、Header等将特定请求导向新服务其余请求仍走旧单体。第三步用“门面”偷梁换柱针对需要修改旧逻辑的场景在旧单体中找到所有调用该功能的代码把方法内部的实现替换为一行RPC调用指向新服务。这样旧单体仍然是入口但实际逻辑已经跑在新服务里了。第四步流量镜像验证针对高风险写操作对于“下单”等核心操作让生产流量同时打在旧单体和新建微服务上异步镜像比对两者的结果和数据库变更。持续一周确认一致率达到99.99%后再正式切流。第五步物理删除新服务稳定运行1~3个月后从旧单体的代码库中直接删除已迁移的类。因为所有调用都已改为RPC删除后编译依然通过。旧单体逐渐瘦身直至完全下线。4. 为什么这么做因为风险可控。每次只迁移一个小功能如果失败了只需在网关层把流量切回旧单体秒级回滚影响面极小。因为业务不中断。在整个迁移过程中系统始终保持可用用户无感知。因为持续交付。你可以按迭代增量迁移每个迭代都有产出团队士气高业务方也看得到进展。5. 有什么原则原则一绝不碰旧代码只做“门面委托”。不修改旧单体的内部逻辑只在入口处加一层转发。这避免引入新的Bug。原则二先“读”后“写”。先迁移查询类功能风险低再迁移写入类功能。原则三新系统必须“活得更久”。新服务上线后不要急于下线旧功能。保持双轨运行一段时间直到你确信新系统足够健壮。五、三者的本质方案本质一句话归纳DDD“业务逻辑的数学建模”。它是对现实世界的抽象把复杂业务拆解为有清晰边界、有明确规则的“领域模型”。“怎么把业务画清楚”康威定律“组织结构的架构映射”。它承认“人”是系统的一部分把沟通成本转化为架构设计的一部分。“怎么把人组织对”扼杀者模式“时间维度上的演进策略”。它承认系统是活着的、会变化的提供了一条低风险的进化路径。“怎么把旧系统换掉”六、三者协同的逻辑闭环业务复杂 → DDD拆分出“订单域”、“库存域”等限界上下文 ↓ 康威定律把团队拆成“订单团队”、“库存团队” ↓ 每个团队在自己的域里用DDD战术设计写代码 ↓ 如果系统是遗留系统 → 用扼杀者模式逐步替换 ↓ 最终每个服务只由一个团队维护每个团队只维护自己的服务 ↓ “改一个需求只改一个服务发一次版”——痛点彻底解决最根本的原则“高内聚、低耦合”不是技术目标而是业务目标。DDD从业务上定义高内聚康威定律从组织上保证低耦合扼杀者模式从时间上实现平滑过渡。三者缺一不可共同构成了微服务拆分与演进的“完整方法论”。
返回列表