DDD为何成为微服务划分的方法论 -- 知识铺
微服务架构的采用与实践
背景
在公司中有一套负责主要盈利业务的核心系统,由于其重要性,成为了产品和业务团队的重点关注对象。他们不断提出新需求并期望快速迭代。然而,由于系统的庞大和复杂性,技术团队难以迅速响应这些需求。产品经理们因此感到不满,担心这会影响公司的竞争力。
采用微服务的原因
出于对上述问题的考量,我们决定引入微服务架构来解决这些问题。实际上,采用微服务有时更多是一个组织层面或政治上的决策,而不仅仅是技术选择。对于规模不是特别大的项目,直接转向微服务可能并不会带来显著的好处,并且还会增加工作量。
微服务应用建议
- 如果预计业务将快速增长,应尽早考虑微服务拆分。
- 当设计需要使用多种不同技术栈时,也应当考虑微服务。
- 若公司具备成熟的技术基础设施,并且业务从一开始就被设计得非常复杂,那么可以立即采用微服务架构。
迁移到微服务的方法
迁移至微服务既可以通过较为激进的方式也可以采取渐进式的策略。
我的实践经验
在我初次尝试微服务时,由于急需利用微服务带来的快速部署等优势,我采用了以下折衷方案:
-
独立边缘业务处理:对于那些可以视为独立边缘业务的需求,直接创建新的独立服务,并通过网络接口与现有老系统集成。
-
核心业务周边需求处理:针对核心业务周围的变动频繁模块进行优先剥离,并逐步分离其他不太变化的部分。 为了确保用户体验不受影响,在实施过程中我还设置了一个代理层,用于管理和转发用户请求到合适的服务端点。 这种方法虽然比较粗犷,但在当时确实帮助我们解决了紧迫的问题。
后续改进
经历这次之后,我对微服务有了更深入的理解。在后续的新项目中,我更加注重于清晰地划分业务功能模块后再构建微服务架构。
步骤概述
- 第一步:明确功能模块:尤其是在新建系统初期,当业务逻辑尚不复杂时,应该先确定好各个功能模块的边界。
理解现有大项目的系统源码
在处理已有的大项目时,首先需要深入理解系统的源码。这涉及到:
-
阅读源码:详细查看代码,理解其结构和逻辑。
-
分析业务文档:结合业务文档,理解源码背后的业务逻辑。
-
梳理业务模块:将复杂的业务流程分解成清晰的模块,便于后续的服务划分。
梳理功能模块的方法
在明确了业务模块之后,下一步是将这些模块转化为独立的服务。这需要:
-
确定服务边界:明确每个服务的职责和边界,确保服务之间的低耦合。
-
创建服务方法:如果是从零开始的项目,可以根据自己的业务划分,直接创建对应的服务方法。
-
服务间联系:确定服务之间的联系和交互方式,确保服务能够协同工作。
如果针对已有项目拆分,那就不好搞了。非得仔细梳理源码,然后根据源码的类和方法,逐次清理出各个模块的之间的方法调用。非常麻烦。
第三步:对方法进行分类
把梳理出来的所有方法做一次分类,分成两类:功能模块直接对外部用户的方法,功能模块内部之间需要调用的方法。
第四步:模块映射服务,方法映射 API
在软件开发过程中,将功能模块映射到服务是一个关键步骤。这个过程通常从简单的一对一映射开始,但实际情况往往更为复杂。以下是详细的步骤和注意事项:
-
初步映射:首先,尝试将每个功能模块直接映射到一个服务。这是最直观的方法,可以作为起点。
-
识别问题:在实际操作中,可能会遇到各种问题,如服务划分过细或过粗、服务职责不清晰等。这些问题需要在实际开发和测试过程中不断发现和调整。
-
调整映射:根据实际问题,对服务映射进行调整。可能需要合并一些服务,或者将一个服务拆分成多个子服务。目标是确保每个服务的职责单一且明确。
-
优化接口:在服务映射确定后,进一步优化API设计。确保API既满足功能需求,又具有良好的扩展性和可维护性。
-
文档记录:最后,详细记录服务和服务之间的映射关系,以及每个服务的API文档。这有助于团队成员理解和使用这些服务。 通过以上步骤,可以较为系统地完成从功能模块到服务的映射工作。
在构建业务模块与服务的一对一映射时,我们通常会遇到一些挑战。以下是对这些挑战的概述和调整策略:
第一步:建立映射假设
-
我们假设业务模块和服务之间可以建立一对一的映射关系。 第二步:梳理业务模块的方法调用
-
详细梳理每个业务模块的方法调用,以确定它们与服务API的对应关系。 第三步:映射业务方法到服务API
-
将业务模块的方法调用映射到相应的服务API方法上。 第四步:进行初步映射
-
根据梳理的结果,建立初步的映射关系。 第五步:根据实际情况做调整
-
根据实际运行情况对映射关系进行调整,主要原因可能包括:
-
网络交互性能问题:服务拆分后,原本模块间的调用变成了网络交互,可能导致性能下降。
-
服务依赖性:某些服务可能需要依赖其他服务,这在映射时需要特别考虑。
-
数据一致性:确保服务间的数据交换能够保持一致性。
-
安全性:确保服务间的交互符合安全标准。
-
可扩展性:考虑未来可能的业务扩展,确保映射关系有足够的灵活性。 调整策略
- 根据上述原因,逐步调整映射关系,以优化性能、保证数据一致性、增强安全性,并提高系统的可扩展性。
在优化网络调用频率时,我们可以考虑两种策略来解决频繁的网络请求问题:
-
批量处理服务间的交互:将多个单独的服务调用合并为一个批量请求可以减少网络开销和延迟。这种方法有助于保持服务拆分带来的灵活性和可维护性。
-
避免服务拆分:如果决定不拆分服务,虽然能够减少因网络通信带来的性能损耗,但这样做会破坏原有的服务架构设计和服务之间的映射关系,可能会导致系统更加难以维护和扩展。 关于同步调用可能引发的问题:
-
当服务在同一进程中以同步方式进行本地调用时,通常不会产生显著的性能影响,因为这些操作发生在同一进程内,执行速度较快且没有额外的网络延迟。
-
然而,在分布式环境下,同步调用可能导致调用方等待响应而造成阻塞。这不仅降低了系统的响应能力,还可能引起雪崩效应,特别是在高并发场景下。 综上所述,对于需要优化网络调用的情况,推荐采取批量处理的方式来进行服务间交互,这样既能保证效率又能维持良好的服务结构。aaaaaaa
在微服务架构中,服务之间的网络调用需要特别考虑容错和阻塞的问题。为了处理这种情况,可以采取以下两种策略:1. 设置超时;2. 将同步方法转换为异步方式。
如果将一些同步方法转换为异步方式,服务的API和以前的方法映射关系可能需要调整。例如,一个方法可能需要对应两个异步API:一个是用于访问,另一个是用于获取响应。
数据一致性问题
在微服务架构中,数据一致性是一个挑战。由于服务之间独立,数据同步和更新变得复杂。通常,微服务架构会采用特定的模式来解决数据一致性问题,这些模式将在后续文章中详细讨论。
核心业务类问题
在复杂的业务系统中,某些核心业务类,如电商系统中的订单类,由于其在多个业务流程中的使用,变得非常庞大和复杂。这类类被称为God类,因为它们包含了大量的字段,并且与许多业务逻辑紧密相关。
God类的问题
-
复杂性: God类通常包含大量的字段和方法,使得代码难以维护和理解。
-
紧密耦合: 由于God类在多个地方被使用,任何更改都可能影响到多个业务流程。
-
难以测试: 由于其复杂性和广泛的依赖性,对God类进行单元测试变得非常困难。
解决方案
-
重构: 将God类拆分成更小的类,每个类负责一部分功能。
-
服务化: 将God类相关的功能拆分到不同的微服务中,以降低耦合度。
-
使用设计模式: 应用设计模式如工厂模式、策略模式等,以提高代码的可维护性和可测试性。
在软件开发过程中,God 类的问题一直是一个挑战。God 类通常包含大量字段,被多个业务模块使用,这使得微服务拆分变得困难。以下是对上述问题的重新组织和结构化描述:
一、God 类的问题
God 类因其庞大的字段数量和广泛的业务依赖性,成为了微服务拆分的障碍。尝试拆分服务时,God 类的存在往往导致拆分工作变得复杂和困难。
问题表现:
- 字段过多:God 类包含大量字段,许多业务都需要使用。
- 拆分困难:God 类的存在使得业务拆分变得复杂。
- 服务丑陋:为了解决God 类问题,不得不将其单独拆分为微服务,但这并非理想的解决方案。
问题后果:
- 缺乏业务逻辑:单独拆分的God 类微服务缺乏明确的业务逻辑。
- API随意增加:由于缺乏限制,任何人都可以随意添加API。
- 服务压力大:God 类微服务被广泛访问,需要集群支持,增加了成本。
二、领域驱动设计的应用
领域驱动设计(DDD)提供了一种新的思考方式,通过引入子域和限界上下文的概念,帮助解决God 类的问题。
核心概念:
- 子域:传统的业务模块划分。
- 限界上下文:明确指出服务包含实现代码,每个子域的服务都是一个限界上下文。
解决方法:
- 拆分God 类:在不同的子域中,将God 类拆分成不同的类,每个类包含原God 类中的部分字段。
- 示例:
- 支付子域:订单类只包含用户和金额字段。
- 物流子域:订单类只包含商品和用户地址字段。
三、实现上的挑战
尽管DDD提供了理论支持,但在实际实现中,还需要解决用户视角的订单信息展示问题。
解决方案:
- API网关聚合:通过微服务的API网关,将各微服务的数据聚合成用户看到的订单。
- 数据转换:API网关负责将用户看到的订单信息转换成各个微服务之间需要的信息。
四、微服务的挑战
微服务架构虽然有其优势,但也带来了新的挑战。
新问题:
- 服务拆分:如何合理拆分服务,避免过度拆分。
- 服务治理:如何管理和维护众多的微服务。
- 数据一致性:在分布式系统中保持数据一致性。
相关文章:
- 微服务的架构模式(上)
- 微服务的架构模式(中)
- 微服务的架构模式(下)
- 微服务虽好,但不适合你 注意:微服务架构需要根据具体业务场景谨慎考虑,并非所有情况都适合采用。
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/geek002/post/20240918/DDD%E4%B8%BA%E4%BD%95%E6%88%90%E4%B8%BA%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%88%92%E5%88%86%E7%9A%84%E6%96%B9%E6%B3%95%E8%AE%BA--%E7%9F%A5%E8%AF%86%E9%93%BA/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com