Dubbo調度機制解析(LoadBalance擴展)

由於項目需求特殊,需要在dubbo中實現一種能指定遠程地址的分發機制,剛開始想在直連的配置上解決,後來發現對於已經加載了dubbo xml配置的spring容器中是無法在代碼層面進行有效的修改的(因爲貌似會重新加載xml文件中原有的配置記錄),另一方面,這種做法會產生併發衝突的隱患。後來經同事提醒,使用了dubbo留出來的擴展點的方法實現了這個功能,也就是實現了AbstractLoadBalance接口,並重寫了doSelect方法,在doSelect方法實現中,根據調度服務方法傳進的參數也就是指定的遠程主機的ip地址和端口進行了過濾,最終返回滿足該條件的Invoker作爲最終的返回值給調用端。

實現過程相對簡單,但是網上資料並不多,簡單記錄下:

1.      首先要繼承AbstractLoadBalance並重寫select方法,並且注意包要和其他dubbo已經提供的LoadBalance類同一級目錄,比如我實現的一個子類:

 

packagecom.alibaba.dubbo.rpc.cluster.loadbalance;

 

import java.io.File;

import java.util.List;

 

import com.alibaba.dubbo.common.URL;

import com.alibaba.dubbo.rpc.Invocation;

import com.alibaba.dubbo.rpc.Invoker;

importcom.alibaba.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance;

 

/**

*

* @author : zhengrf1

* @date 創建時間:2017年11月1日 下午5:07:15

* @version 1.0

* @parameter 

* @since 

* @return 

*/

public class AppointLoadBalance extendsAbstractLoadBalance {

 

         /*@author : zhengrf1

          * @date 創建時間:2017年11月1日 下午5:07:16

          * @seecom.alibaba.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance#doSelect(java.util.List,com.alibaba.dubbo.common.URL, com.alibaba.dubbo.rpc.Invocation)

          */

         @Override

         protected<T> Invoker<T> doSelect(List<Invoker<T>> arg0, URLarg1, Invocation arg2) {

                   //TODO Auto-generated method stub

                   System.out.println("helloworld"+arg2.getMethodName()+arg2.getArguments().length+arg2.getArguments()[0].toString());

                   for(Invoker<T>invoker : arg0){

                            System.out.println(invoker.getUrl().getAddress()+invoker.getUrl().getHost()+invoker.getUrl().getPort());

                            if(invoker.getUrl().getHost().equals(arg2.getArguments()[2].toString())){

                                     returninvoker;

                            }

                   }

                   returnnull;

         }

 

}

 

--在該類邏輯中,取到了調度服務接口的第三個參數也就是指定的ip和端口,並且以此來過濾所有的invoker,返回滿足條件的invoker。並且注意包聲明:package com.alibaba.dubbo.rpc.cluster.loadbalance;

 

2.在dubbotisson-2.5.3.2.jar下面的META-INF/dubbo/internal/目錄下找到com.alibaba.dubbo.rpc.cluster.LoadBalance文件,並且在該文件最後一行中添加:

Appoint= com.alibaba.dubbo.rpc.cluster.loadbalance.AppointLoadBalance

 

--我是直接修改了dubbotisson-2.5.3.2.jar下的該文件,並重新加入項目的依賴外包,網上說比較規範的做法是自己創建一個jar包,並且在同樣的目錄層次下創建同名的文件,並把這行配置內容寫進去。這樣,dubbo啓動時會自動掃描所有com.alibaba.dubbo.rpc.cluster.LoadBalance文件進行合併,另外也可以同時把自己實現的AbstractLoadBalance子類加入jar包,當然這種做法我沒真正實踐過。

 

3.在xml配置中,配置service層:

<dubbo:serviceinterface="operatingPlatform.DispatchServer"  ref="DispatchServerImpl"executes="20" loadbalance="appoint"/>

 

--默認的loadbalance是RandomLoadBalance,所以要顯式修改成自己的。

 

---到此爲止,對於dubbo的均衡策略就完成了。但是隻截取這一層看起來有點糊塗,所以最好明白整個dubbo的路由均衡機制。

 

--簡單來說,就是Cluster的子類通過自己持有的FailoverClusterInvoker,首先調用Directory的子類的list方法 獲取所有符合條件的Invoker,並放置在List容器中,然後調用Router的子類調用route方法過濾掉不滿足路由條件的Invoker,然後調用LoadBalance的子類的Select方法,選中最後需要調用的Invoker,最後調用該Invoker的Invoke方法實現遠程調用。

可以通過下面的異常報錯流程看出一二:

Exception in thread "main"java.lang.NullPointerException

         atcom.alibaba.dubbo.rpc.cluster.support.AbstractClusterInvoker.doselect(AbstractClusterInvoker.java:135)

         atcom.alibaba.dubbo.rpc.cluster.support.AbstractClusterInvoker.select(AbstractClusterInvoker.java:115)

         atcom.alibaba.dubbo.rpc.cluster.support.FailoverClusterInvoker.doInvoke(FailoverClusterInvoker.java:73)

         atcom.alibaba.dubbo.rpc.cluster.support.AbstractClusterInvoker.invoke(AbstractClusterInvoker.java:227)

         atcom.alibaba.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker.invoke(MockClusterInvoker.java:72)

         atcom.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler.invoke(InvokerInvocationHandler.java:52)

         atcom.alibaba.dubbo.common.bytecode.proxy0.dispatch(proxy0.java)

         atoperatingPlatform.DispatchClient.main(DispatchClient.java:31)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章