Dubbo暴露JsonRPC的步驟

擊水三千里發表於2019-03-14

一、背景介紹

 最近一個專案需要給node端同學直接提供dubbo訪問。
dubbo預設是使用hessian協議的,node是可以直接呼叫dubbo的預設協議的,或者呼叫dubbo的其他原生協議。
為什麼不考慮直接使用hessian呢,因為hessian是基於http的,消耗巨大,並且會有亂碼的問題
所以後端dubbo提供的服務考慮使用jsonrpc協議,但是dubbo原生是不支援jsonrpc協議的,需要在dubbo上進行一些擴充。
這個擴充類可以使用第三方包dubbo-rpc-jsonrpc。 

 

二、JsonRPC介紹

json-rpc是基於json的跨語言遠端呼叫協議,比xml-rpc、webservice等基於文字的協議傳輸資料格小;相對hessian、Java-rpc等二進位制協議便於除錯、實現、擴充套件,是非常優秀的一種遠端呼叫協議。

 

三、export和import

Dubbo服務端介面export(匯出)是將介面資訊註冊到註冊中心Registry的過程。而客戶端import(匯入)遠端介面是通過從註冊中心Registry訂閱遠端服務介面,收到通知後拉取到本地的過程。
註冊和訂閱的過程,不需要修改服務端本地的類和方法,只需保證客戶端和服務端共同引用一個包含介面的jar包。服務端和客戶端分別編寫簡單的dubbo介面配置xml檔案(或註解的方式),容器啟動時就自動註冊和訂閱了。

 

四、如何引入JsonRPC

1、引入maven依賴包

<dependency>
      <groupId>com.ofpay</groupId>
      <artifactId>dubbo-rpc-jsonrpc</artifactId>
      <version>1.0.1</version>
      <exclusions>
           <exclusion>
               <groupId>org.springframework</groupId>
               <artifactId>spring</artifactId>
            </exclusion>
      </exclusions>
</dependency>
 
 

2、apollo配置

Dubbo.JsonRPC

3、程式碼實現

3.1、apollo變更的監聽

@Component
public class DeviceApolloConfigChangeListener {

    private final LogUtil logger = new LogUtil(this.getClass());
    @Autowired
    private RefreshScope refreshScope;
 

    @ApolloConfigChangeListener({"Dubbo.JsonRPC"})
    private void dubboChange(ConfigChangeEvent changeEvent) {
        //update injected value of batch if it is changed in Apollo
        Set<String> changes = changeEvent.changedKeys();
        String key = "spring.jsonrpc.beans";
        if(changes.contains(key)){
            logger.info("配置[" + key+"]發生變化:" + changeEvent.getChange(key));
            refreshScope.refresh("apolloDubboConfig");
            ApplicationSmarLifecycle applicationSmarLifecycle = SpringUtil.getBean("applicationSmarLifecycle");
            applicationSmarLifecycle.refresh();
        }
    }
}

3.2、Spring容器所有例項載入完成之後,暴露指定的dubbo服務 

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.ServiceConfig;
import org.apache.poi.hssf.record.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Component
public class ApplicationSmarLifecycle implements SmartLifecycle {

    
    private List<ServiceConfig<T>> serviceConfigList  = new ArrayList<>();

    @Autowired
    ApplicationConfig applicationConfig;

    @Autowired
    private RegistryConfig registryConfig;

    @Autowired
    private DubboConfig dubboConfig;

    private boolean isRunning = false;



    private static final Logger logger = LoggerFactory.getLogger(ApplicationSmarLifecycle.class);

    @Override
    public void start() {
        this.init();
        isRunning = true;
    }


    @Override
    public int getPhase() {
        return 0;
    }

    @Override
    public boolean isAutoStartup() {
       //SmartLifecycle子類的才有的方法,當isRunning方法返回true時,該方法才會被呼叫。
        return true;
    }
    @Override
    public boolean isRunning() {
        return isRunning;
    }

    @Override
    public void stop(Runnable callback) {
        callback.run();
        isRunning = false;
    }

    @Override
    public void stop() {

        isRunning = false;

        serviceConfigList.forEach(serviceConfig->{
            serviceConfig.unexport();
        });
    }

    public void init(){
        ProtocolConfig jsonpcProtocol = new ProtocolConfig();
        jsonpcProtocol.setName(dubboConfig.getJsonrpcName());
        jsonpcProtocol.setPort(dubboConfig.getJsonrpcPort());

        //在這裡通過apollo配置哪些dubbo服務需要以JsonRP服務的方式暴露
        List<String> beanNames = Arrays.asList(dubboConfig.getJsonrpcBeans().split(","));
        beanNames.forEach(beanName->{
            ServiceConfig<T> serviceConfig = new ServiceConfig<>();
            serviceConfig.setApplication(applicationConfig);
            serviceConfig.setRegistry(registryConfig);
            //自定義為jsonrpc協議
            serviceConfig.setProtocol(jsonpcProtocol);
            //自定義服務版本號
            serviceConfig.setVersion(dubboConfig.getJsonrpcVersion());
            serviceConfig.setGroup("myGroup");
            //需要暴露jsonrpc的dubbo服務
            serviceConfig.setRef(SpringUtil.getBean(beanName));
            //設定dubbo服務對應的介面
serviceConfig.setInterface(SpringUtil.getBean(beanName).getClass().getInterfaces()[0]);
            serviceConfig.export();
            serviceConfigList.add(serviceConfig);
        });
    }

    //apollo配置有更新時重新發布jsonrpc服務
    public void refresh(){
        this.destroy();
        this.init();
    }
}

五、觀察dubbo-admin控制檯裡引數

dubbo-admin

 

相關文章