淘先锋技术网

首页 1 2 3 4 5 6 7

业务背景

实际开发中,经常会碰到需要A服务调用B服务,B服务接收到请求返回调用成功,实际处理需要异步,当异步处理完成之后,再通知A,如下图:

5a063fdc224713e5a8cf3455ec181d98.png

我们希望的B提供的接口与回调的方式是统一的,这样B就能实现与业务解耦,业务有增加,B服务不需要做任何变更即可支撑。

怎么实现

12步骤是同步流程,我们可以有很多方式对接B。在java微服务中,我们可以通过http的请求,可以通过mq的方式,也可以通过dubbo(rpc)。

3步骤在java微服务中,也可以通过上述3种方式来操作,可以与1方式相同,也可以不同。

基于dubbo方案

对应标题,基于dubbo的方案,来实现样例

有接触dubbo的同学都知道,dubbo是通过接口实现的方式提供服务的,那么就有可能出现同一个接口有多个实现,provider就有很多同一个接口实现的服务,这个时候就需要有唯一标识来区分提供的服务. consumer通过唯一标识来指定调用具体的服务。

  • 通常我们可以通过以下几个方式来区分

    • address:注册中心地址

    • group: dubbo服务分组

    • version: dubbo服务版本

以下为基于dubbo具体的实现方案,默认为同一个注册中心,使用不同的group来区分

项目结构

基于spring boot 2.3.0 + dubbo 2.7.7 + zookeeper的实现

主要的maven依赖:

1. common

还有一个很重要的需要配置dubboFilter

1a728dac6115ebb80e7084e5c21458cd.png

文件路径: resources/META-INF/dubbo/org.apache.dubbo.rpc.Filter
文件内容: dubboFacadeFilter=com.github.dubbo.DubboFacadeFilter

2. service-A

A1 A2 是一模一样的,只是spring.application.id 配置不同,标识为不同的服务
为了方便测试,创建为一个spring boot web项目

3.service_B

也创建为一个spring boot web项目,提供异步延迟动态回调的功能

// 动态调用CallbackInvoker
~~~
@Component
public class CallbackInvoker implements ApplicationContextAware {

private static Map> referenceConfigMap = new ConcurrentHashMap<>();
private static Map registryConfigMap = new ConcurrentHashMap<>();
private ApplicationContext applicationContext;
/**
* 获取注册中心地址
*
* @param group
* @return
*/
private RegistryConfig getRegistry(String group) {
RegistryConfig registryConfig = registryConfigMap.get(group);
if (null == registryConfig) {
registryConfig = new RegistryConfig();
RegistryConfig bean = applicationContext.getBean(RegistryConfig.class);
registryConfig.setAddress(bean.getAddress());
registryConfig.setProtocol(bean.getProtocol());
registryConfigMap.put(group, registryConfig);
}
return registryConfig;
}
/**
* 获取服务的代理对象
* @param applicationName
* @param group
* @return
*/
private ReferenceBean getReferenceConfig(String applicationName, String group) {
ReferenceBean referenceBean = referenceConfigMap.get(applicationName);
if (null == referenceBean) {
referenceBean = new ReferenceBean<>();
referenceBean.setRegistry(getRegistry(group));
referenceBean.setInterface(CallbackFacade.class);
referenceBean.setGroup(group);
referenceConfigMap.put(applicationName, referenceBean);
}
return referenceBean;
}
public void invoke(CallbackDTO callbackDTO) {
ReferenceBean referenceConfig = getReferenceConfig(callbackDTO.getApplicationName(), callbackDTO.getGroup());
if (null != referenceConfig) {
CallbackFacade callback = referenceConfig.get();
if (callback != null) {
callback.invoke(callbackDTO);
}
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
测试结果

总结

上面回调实现方案是基于dubbo的方式:

  1. 在spring cloud中也可以基于http的方式,通过服务名的方式区分。

  2. 也可以mq的方式通过发送不同的队列,对应的服务进行消费。

方式有很多种,主要目的是为了让接入方,不需要编写多余的代码,完全解耦的方式实现。