Dubbo调度机制解析(LoadBalance扩展)

来源:互联网 发布:成都java程序员工资 编辑:程序博客网 时间:2024/05/18 11:21

由于项目需求特殊,需要在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)

原创粉丝点击