目前微服务架构应用非常普遍,我们在获得其带来的优势的同时,需要思考是否解决了其带来的问题。
在以往学习Spring Boot的过程中,就遇到关于Service循环依赖的问题。微服务架构中服务间相互依赖的问题仍然十分普遍,针对这个问题,我咨询过公司的架构师,他们的回答是无法解决/避免。显然上述回答是让我无法信服的,个人认为这是一种没有深度思考的回答,是一种仅站在技术维度,而未站在管理维度思考的结果。
分布式单体
为什么这么认为,首先我们需要考虑一个问题,为什么我们要从单体架构转向微服务架构。其中一个核心且普遍的原因是随着持续的迭代,单体架构内部服务间耦合度越来越高,逻辑越来越复杂,对一个业务点的变更常常导致牵一发而动全身的后果。答案显而易见,如果微服务间的服务调用缺少规范,那么同样在后续迭代过程中会面临同样的问题,受微服务特性的影响,这种问题的复杂度可能会更高。 之前看到国外技术专家针对该问题的论述,一针见血的将其定义为:分布式单体。
业务场景分析
为什么会出现服务间相互依赖的问题,需要根据实际的业务场景(针对业务场景分析,作为技术/研发人员常常会陷入技术思维而脱离业务场景开发,这是由行业或角色分工导致的)进行分析。
举个例子,实际业务中通常从建单(创建单据)开始,通过单据驱动业务流程,例如根据单据创建一个任务,任务执行完成后单据状态变更。在微服务架构中,可能会涉及两个服务间的交互:单据服务和任务服务。两个简单流程:一是单据服务调用任务服务创建任务;二是任务服务调用单据服务更新单据状态。为便于区分,将流程一定义为正向流程,流程二定义为逆向流程。
一般情况下,正向流程会设计为同步调用,这是由业务特性决定的,例如单据开始【执行作业】,单据状态变更的同时需要保证任务创建成功,否则任务无法正常驱动。通过业务场景分析逆向流程是否需要同步调用,任务执行成功通知单据状态变更:任务执行成功状态变更实际上并不受单据状态更新成功与否的影响,即任务执行完成只需要通知单据即可,可设计为异步通知。这种场景下一般可借助消息中间件来完成。
解决方案
根据业务特性,我们在实际的开发中,正向流程中服务依赖一般设计为同步调用;逆向流程通过消息通知方式,即任务完成后发送领域事件(领域驱动设计),单据服务监听任务消息完成状态更新。 以上处理方式保证了服务间只有单向调用,彻底隔离了服务间相互调用的影响,是完全自上而下的调用方式,同时在设计中也借鉴了EDA架构(事件驱动架构)的思想。
优势:
- 一是完全自上而下的服务调用,结构简单清晰,管理、维护、学习成本低;
- 二是满足大部分业务场景需求;
- 三是逆向流程采用EDA架构,伸缩性、性能均得到提升