记因循环依赖的解决方案
前言
循环依赖分为2类:
- RPC服务间(dubbo、http)循环依赖
- 应用间循环依赖
-
Dubbo缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,防止Spring初始化完成。这种情况我们就叫做RPC服务间循环依赖。出现了循环依赖,必须有一方先启动。所以这种问题是一定需要解决的。
-
应用间循环依赖大致情况如下: A应用调用B应用的服务,B应用也会调用A应用的服务,无论是间接调用还是直接调用。 这种循环依赖刚开始不会出现问题 ,但随着代码变更,有可能会发展为RPC服务间循环依赖。
可以通过check=”false”关闭检查来避免 Dubbo的循环依赖的报错,但是我认为这个只是权益之计。
应用间循环依赖
当前我们应用中并没有出现RPC服务间循环调用,但是出现了应用间循环调用。下面就是这个🌰就是这种情况,我简单描述下大致的情况。
- marketing-base会调用site-base服务中的SiteGroupService、SiteService接口用来查询集团、店铺、微店的信息。
- site-base里有监听集团初始化的消息,然后执行集团初始化,过程中会调用marketing-base的服务以初始化文章、海报数据。
上面这个例子是应用间循环依赖,一不小心可能写出暴雷的代码。这里应该尽快把这个坑填掉。
处理方案
针对应用间循环依赖,大致的解决办法
团队协作模式:
- 重新划分归属,把职责给一个方向
- 共享内核(提出一个公共服务)
通信集成模式:
- MQ解耦服务间的依赖
由于上述的2个服务早已开发完毕,且比较成熟的应用,而且直接的依赖还是比较少的。此时MQ看起来是一个比较好的方案了。
这里考虑到site-base
比marketing-base
是更加基础的服务,所以图一中上边的调用流程不变,下方更改为site-base
发送消息,然后marketing-base
来消费消息的方式。如图二所示。
Show me Code
首先,我们需要向运维或者自己在单机环境下,新创建一个Topic。我这里新创建一个名叫: newcar_siteinit_basicinfo_test 的主题。
生产者配置
在config/user/beans中添加一个spring xml 配置文件 application-mq.xml。
application-mq.xml
1 <!--ons config--> 2 <bean id="producerConfig" class="com.souche.optimus.mq.aliyunons.ONSProducerConnConfig"> 3 <property name="accessKey" value="${ons.access.key}"/> 4 <property name="secretKey" value="${ons.secret.key}"/> 5 </bean> 6 7 <!-- 集团初始化 发送者 --> 8 <bean id="groupInitProducerInvoker" class="com.souche.optimus.mq.aliyunons.ONSProducerInvoker"> 9 <property name="producerId" value="${ons.groupinit.producer.id}"/> 10 <property name="config" ref="producerConfig"/> 11 </bean> 12 13 <bean id="groupInitProducer" class="com.souche.optimus.mq.aliyunons.ONSProducer"> 14 <property name="topic" value=