天天看點

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的方式通過發送不同的隊列,對應的服務進行消費。

方式有很多種,主要目的是為了讓接入方,不需要編寫多餘的代碼,完全解耦的方式實作。