Dubbo源码笔记(二)

Dubbo源码学习笔记

服务发现

Dubbo服务引用分两种:饿汉式和懒汉式,默认使用的时懒汉式。第一种饿汉式在Spring容器初始化时,调用ReferenceBeanafterPropertiesSet方法时引用服务;第二种懒汉式,在对应服务被注入到其他类中时,Spring会调用getObject()方法,完成服务引用。

有三种引用服务方式:引用本地服务,通过直接连接引用远程服务,通过注册中心引用远程服务。无论哪种方式,最后都可以获得一个或一组Invoker实例。对于一组Invoker实例,会交由AbstractClusterInvoker管理,对于一组Invoker,AbstractClusterInvoker内部会根据配置的LoadBalance策略进行负载均衡。

Zookeeper中的消费者注册和节点订阅

消费者在向注册中心注册消费者的时候,还会订阅节点的变更。

 private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
    RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
    directory.setRegistry(registry);
    directory.setProtocol(protocol);
    // all attributes of REFER_KEY
    Map<String, String> parameters = new HashMap<String, String>(directory.getUrl().getParameters());
    URL subscribeUrl = new URL(CONSUMER_PROTOCOL, parameters.remove(REGISTER_IP_KEY), 0, type.getName(), parameters);
    if (!ANY_VALUE.equals(url.getServiceInterface()) && url.getParameter(REGISTER_KEY, true)) {
        directory.setRegisteredConsumerUrl(getRegisteredConsumerUrl(subscribeUrl, url));
        //向注册中心注册消费者
        registry.register(directory.getRegisteredConsumerUrl());
    }
    directory.buildRouterChain(subscribeUrl);
    //订阅节点,然后notify,然后刷新invokers列表
    directory.subscribe(subscribeUrl.addParameter(CATEGORY_KEY,
            PROVIDERS_CATEGORY + "," + CONFIGURATORS_CATEGORY + "," + ROUTERS_CATEGORY));
    //通过注册中心拿到的provider可能会有多个,在这里合并
    Invoker invoker = cluster.join(directory);
    ProviderConsumerRegTable.registerConsumer(invoker, url, subscribeUrl, directory);
    return invoker;
}

register就是向注册中心注册,不通的注册中心实现也不尽相同,zk就是创建一个临时节点(provider创建的是永久节点)。订阅的话,zookeeper就是添加子节点监听事件。

动态代理和回声测试

Invoker 是实体域,它是 Dubbo 的核心模型,其它模型都向它靠扰,或转换成它。 它代表一个可执行体,可向它发起 invoke 调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。

invoker创建完以后,需要的就是代理对象,我们通过代理对象发起调用。

生成的代理对象,除了实现了provider提供的接口,还实现了EchoServiceEchoService是用于检测服务是否可用的。

if (interfaces == null) {
    interfaces = new Class<?>[]{invoker.getInterface(), EchoService.class};
}