1 dubbo源码之启动时检查

来源:互联网 发布:js怎么判断日期相等 编辑:程序博客网 时间:2024/06/04 18:15
dubbo服务引用,在客户端启动时可以控制是否检查依赖服务是否可用。  


dubbo官方使用手册如下:
Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 check="true" 。
可以通过 check="false" 关闭检查,例如,测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动。
另外,如果你的 Spring 容器是懒加载的,或者通过 API 编程延迟引用服务,请关闭 check,否则服务临时不可用时,会抛出异常,拿到 null 引用,如果 check="false" ,总是会返回引用,当服务恢复时,能自动连上。
原文地址:http://dubbo.io/books/dubbo-user-book/demos/preflight-check.html




dubbo客户端启动服务引用的过程:


1、将服务接口转化为invoker对象
   a 通过Spring的Schemas解析自定义reference标签
   b ReferenceBean实现FactoryBean接口,提供获取远程服务对象的入口
   c ReferenceConfig 将服务接口转化为Invoker对象
     1) 本地服务接口:InjvmProtocol.refer()方法,直接new InjvmInvoker<T>()
     2)远程服务接口:RegisterProtocol.refer()
        首先:连接注册中心,Registry registry = registryFactory.getRegistry(url);
再次:往注册中心注册consumer几点 registry.register
然后:往注册中心发送订阅请求,监听providers节点,通知刷新invoker列表,将invoker存放到RegisterDirectory.urlInvokerMap中保存
最后:创建invoker对象,直接new FailoverClusterInvoker<T>


2、将invoker对象转化为客户端对象


   a 通过JDK的动态代理,将invoker转换为客户端对象 Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker))








在客户端引用服务的过程中,是如何检查服务是否可用呢?
源码如下:
在ReferenceConfig.java的createProxy()中有如下代码:


private T createProxy(Map<String, String> map) {
//此处省略n行代码....
Boolean c = check;
if (c == null && consumer != null) {
    c = consumer.isCheck();
}
if (c == null) {
    c = true; // default true
}
if (c && !invoker.isAvailable()) {
    throw new IllegalStateException("Failed to check the status of the service " + interfaceName + ". No provider available for the service " + (group == null ? "" : group + "/") + interfaceName + (version == null ? "" : ":" + version) + " from the url " + invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion());
}
//此处省略n行代码....
}


consumer为自定义标签对象ConsumerConfig,isCheck(),即判断配置文件中是否存在check配置项,如果没有,默认为true,即如果远程服务部存在,则抛出异常
如果配置了check="false",则进一步判断invoker.isAvailable();


invoker.isAvailable()源码如下:


RegistryDirectory.isAvailable()


public boolean isAvailable() {
        if (isDestroyed()) {
            return false;
        }
        Map<String, Invoker<T>> localUrlInvokerMap = urlInvokerMap;
        if (localUrlInvokerMap != null && localUrlInvokerMap.size() > 0) {
            for (Invoker<T> invoker : new ArrayList<Invoker<T>>(localUrlInvokerMap.values())) {
                if (invoker.isAvailable()) {
                    return true;
                }
            }
        }
        return false;
}


此处判断urlInvokerMap中的invoker.isAvailable();如果urlInvokerMap为空,则直接返回false


而urlInvokerMap中的数据在哪来的呢?
即上面提到的1->a->2->然后
然而urlInvokerMap中的invoker最根本的就是DubboInvoker对象,而DubboInvoker.isAvailable()源码如下:
public boolean isAvailable() {
        if (!super.isAvailable())
            return false;
        for (ExchangeClient client : clients) {
            if (client.isConnected() && !client.hasAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY)) {
                //cannot write == not Available ?
                return true;
            }
        }
        return false;
   }
 
 在这可以看出,最终是判断连接是否正常,是否可以连接