说说微服务循环依赖

2021-08-06 11:33:15 浏览数 (2)

一、什么是循环依赖

循环依赖的主要形式是直接调用,大概分2种情况,接口间的和应用间:

打个比方,某个应用A提供一个服务S1(Dubbo一般对应一个接口),这个服务提供一个接口I11和I12,而应用B提供另一个服务S2,这个服务提供接口I21,I22;

1、接口循环依赖

A.S1.I11——》B.S2.I21——》A.S1.I11

即I11接口调用I21接口,而I21接口的实现又调用I11;

2、应用循环依赖

A.S1.I11——》B.S2.I21——》A.S1.I12

I11调用I21,而后者又调用I12。

实际情况中1的情况比较少见,2的情况应该比较多,即两个应用A和B,A有调用B的代码,B又有调用C的代码。

二、循环依赖的坏处

1、服务功能不内聚,耦合严重,导致研发效率低下

假设A依赖B,B又依赖A,会导致每次A和B部署的时候必须耦合,部署了A就得部署B,不然就会报错;

上面这些还不算严重的,比较麻烦的是A升级或者改了些接口,B要测试下;反过来B改了接口A也要测试下,浪费研发和测试资源;

2、增加了系统的复杂性,很容易出错

一些线上操作升级可能也会比较麻烦,像我们在升级JDK8的时候就必须梳理各种依赖关系,梳理不当就可能会有线上故障;

3、系统的扩展性受到限制

这里的扩展性分系统和业务2方面,系统上来说假如大促我要升级扩容,如果正常不依赖其它应用,或者只依赖少量应用,只升级自己就可以了,如果依赖了其它应用,还得考虑其它应用的容量;还涉及到部署的情况,当你的业务做的很大,以前只是垂直应用,现在升级成平台型应用的时候,对部署有了更高的要求,可能要单独的隔离环境进行部署,如果依赖了不依赖的应用,会使这些几乎不可能。

业务扩展性也是一样的,如果业务发展比较快,要支持更多的场景,那就必须考虑新的业务和这些依赖的应用是否兼容,增加研发成本,也不利于扩展。

三、如何避免循环依赖

按上面的情况,如果应用A依赖B,B依赖A,要做到不循环依赖,有以下办法:

1、改为异步调用

即发送MQ消息,这样发送方就不用关心消费方的存在了。

2、将依赖的部分抽取到更下层的公共服务中

即做到只能A依赖B,则把B依赖A的部分分到另一个服务C中,这样就变成A依赖B,B依赖C了。

3、不依赖

即不依赖相关的服务了,这个场景实际情况也有可能有,即一个系统做了它不应该做的事,可能把这段代码去掉或者换种方式。

四、举例

其实循环依赖的根本原因是我们没有考虑清楚系统的边界,有些功能是应用不该关心的就应该果断的去掉。

1、支付依赖用户

我们以前做的支付系统刚开始的时候是依赖用户系统的,即付款后支付系统会调用用户是否存在,是否有效,这样带来以下问题:

A、无法满足新业务场景

像一些新的场景,如商城现在要做不登录付款,支付就得改了,因为这个用户根本不存在;

B、无法支撑平台型业务

现在要支持一些第三方支付的时候,也是要改,因为第三方的账号和我们根本是不打通的。

综合原因是因为支付不应该关心账号,它只关心付款、退款、第三方网关相关的业务场景就可以了,用户只是其中一种验证调用方的手段,有很多种解决方案,像服务端APP授权和签名的方式就可以了。

2、发货系统和售后系统相互依赖

即有个发货系统,我们叫它W吧,售后系统我们叫它C吗,会出现两者互相调用的情况。

其实只要我们好好想一下,发货系统应该是一种更基础的能力,它不应该知道售后系统的存在,应该是售后单向依赖发货系统才对,细节这里就不聊了。

0 人点赞