天天看点

dubbo yml配置_基于dubbo动态调用实现的回调

业务背景

实际开发中,经常会碰到需要A服务调用B服务,B服务接收到请求返回调用成功,实际处理需要异步,当异步处理完成之后,再通知A,如下图:
dubbo yml配置_基于dubbo动态调用实现的回调
我们希望的

B

提供的接口与回调的方式是统一的,这样

B

就能实现与业务解耦,业务有增加,

B

服务不需要做任何变更即可支撑。

怎么实现

1

2

步骤是同步流程,我们可以有很多方式对接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

dubbo yml配置_基于dubbo动态调用实现的回调

文件路径: 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的方式通过发送不同的队列,对应的服务进行消费。

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