2 dubbo源码之集群容错实现

来源:互联网 发布:java判断是否有双引号 编辑:程序博客网 时间:2024/05/19 08:03
dubbo提供了多种集群容错方式:Failover(失败自动切换)、Failfast(快速失败)、Failsafe(失败安全)、Failback(失败自动恢复)、Forking(并行调用多个服务器)


dubbo官网原文介绍:http://dubbo.io/books/dubbo-user-book/demos/fault-tolerent-strategy.html


集群模式配置如下:
<dubbo:service cluster="failover" />

<dubbo:reference cluster="failover" />






客户端启动,引用远程服务接口时:


ReferenceConfig.java中有两个静态成员变量:
 
 private static final Protocol refprotocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();


 private static final Cluster cluster = ExtensionLoader.getExtensionLoader(Cluster.class).getAdaptiveExtension();


通过扩展点获取Protocol对象为动态生成的Protocol$Adaptive.java的对象,Cluster对象也是动态生成的Cluster$Adaptive的对象
Protocol$Adaptive.refer()方法中,通过getExtension(name)获取对象时,会通过dubbo的IOC将cluster的扩展点对象设置到Protocol实现类的cluster属性,值为:Cluster$Adaptive对象


在RegisterProtocol.doRefer()方法中cluster.join(directory),即Cluster$Adaptive.join()


动态生成的Cluster$Adaptive的源码为:
public class Cluster$Adaptive implements com.alibaba.dubbo.rpc.cluster.Cluster {
    public com.alibaba.dubbo.rpc.Invoker join(com.alibaba.dubbo.rpc.cluster.Directory arg0) throws com.alibaba.dubbo.rpc.RpcException {
        if (arg0 == null)
            throw new IllegalArgumentException("com.alibaba.dubbo.rpc.cluster.Directory argument == null");
        if (arg0.getUrl() == null)
            throw new IllegalArgumentException("com.alibaba.dubbo.rpc.cluster.Directory argument getUrl() == null");
        com.alibaba.dubbo.common.URL url = arg0.getUrl();
        String extName = url.getParameter("cluster", "failover");
        if (extName == null)
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.cluster.Cluster) name from url(" + url.toString() + ") use keys([cluster])");
        com.alibaba.dubbo.rpc.cluster.Cluster extension = (com.alibaba.dubbo.rpc.cluster.Cluster) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.cluster.Cluster.class).getExtension(extName);
        return extension.join(arg0);
    }
}


其中extName是在url的参数中获取的,默认为failover,
默认的failover,扩展点对象extension为FailoverCluster对象,在FailoverCluster.join()方法中new FailoverClusterInvoker


在此处可以看到,集群模式配置再次起到了作用。


集群模式是如何工作的呢?




客户端调用远程服务接口方法时,例如:


private DemoService demoService;


public void test(){


String result = demoService.sayHello();


}


该处的demoService.sayHello()即为客户端调用远程服务方法


远程服务接口对象是有JDK动态代理生成的(不清楚的请看上一篇文章),而dubbo是由InvokerInvocationHandler实现的InvocationHandler接口
在远程调用过程中,其实就是调用InvokerInvocationHandler.invoker方法。
源码如下:
public class InvokerInvocationHandler implements InvocationHandler {


    private final Invoker<?> invoker;


    public InvokerInvocationHandler(Invoker<?> handler) {
        this.invoker = handler;
    }


    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        Class<?>[] parameterTypes = method.getParameterTypes();
        if (method.getDeclaringClass() == Object.class) {
            return method.invoke(invoker, args);
        }
        if ("toString".equals(methodName) && parameterTypes.length == 0) {
            return invoker.toString();
        }
        if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
            return invoker.hashCode();
        }
        if ("equals".equals(methodName) && parameterTypes.length == 1) {
            return invoker.equals(args[0]);
        }
        return invoker.invoke(new RpcInvocation(method, args)).recreate();
    }


}


而此处使用到的invoker就是上面Cluster的动态Adaptive类join方法返回的invoker,默认是FailoverCluster.join()方法new的FailoverClusterInvoker对象




下面来看各种集群模式是如何工作的:
1、FailoverCluster
原创粉丝点击