dubbo源码分析6 -- 注册协议RegistryProtocol

@SPI("dubbo")
public interface Protocol {

    /**
     * 获取缺省端口,当用户没有配置端口时使用。
     * 
     * @return 缺省端口
     */
    int getDefaultPort();

    /**
     * 暴露远程服务:<br>
     * 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext().
     * setRemoteAddress();<br>
     * 2. export()必须是幂等的,也就是暴露同一个URL的Invoker两次,和暴露一次没有区别。<br>
     * 3. export()传入的Invoker由框架实现并传入,协议不需要关心。<br>
     * 
     * @param <T> 服务的类型
     * @param invoker 服务的执行体
     * @return exporter 暴露服务的引用,用于取消暴露
     * @throws RpcException 当暴露服务出错时抛出,比如端口已占用
     */
    @Adaptive
    <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;

    /**
     * 引用远程服务:<br>
     * 1. 当用户调用refer()所返回的Invoker对象的invoke()方法时,协议需相应执行同URL远端
     * export()传入的Invoker对象的invoke()方法。<br>
     * 2. refer()返回的Invoker由协议实现,协议通常需要在此Invoker中发送远程请求。<br>
     * 3. 当url中有设置check=false时,连接失败不能抛出异常,并内部自动恢复。<br>
     * 
     * @param <T> 服务的类型
     * @param type 服务的类型
     * @param url 远程服务的URL地址
     * @return invoker 服务的本地代理
     * @throws RpcException 当连接服务提供方失败时抛出
     */
    @Adaptive
    <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;

    /**
     * 释放协议:<br>
     * 1. 取消该协议所有已经暴露和引用的服务。<br>
     * 2. 释放协议所占用的所有资源,比如连接和端口。<br>
     * 3. 协议在释放后,依然能暴露和引用新的服务。<br>
     */
    void destroy();

}

ServiceBean都是对外提供服务,所以用的都是export
而ReferenceBean是调用服务,所以都是用refer


export

  • 根据url中的export(dubbo://…)对外地址,dubbo提供服务(再启动之前,会有一些filter单性链表) doLocalExport(….)
  • 获取到ZookeeperRegistry(根据协议),向zookeeper注册/dubbo/xxService/providers/地址
  • 订阅重写
public <T> Exporter<T> export(final Invoker<T> originInvoker)  {
   //1. dubbo对外提供接口
   final ExporterChangeableWrapper<T> exporter = doLocalExport(
   originInvoker);
   //2. 获取Registry实例
   final Registry registry = getRegistry(originInvoker);
   //3. 向zookeeper注册/dubbo/xxService/providers/地址
   final URL registedProviderUrl = getRegistedProviderUrl(originInvoker);
   registry.register(registedProviderUrl);
   //4.订阅override数据
   /**
   provider://10.118.14.204:20890/com.test.ITestService?
       category=configurators&..
   **/
   final URL overrideSubscribeUrl = getSubscribedOverrideUrl(
           registedProviderUrl);
   final OverrideListener overrideSubscribeListener = new 
       OverrideListener(overrideSubscribeUrl);
   overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);
   registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);

   //保证每次export都返回一个新的exporter实例
   return new Exporter<T>() {
       public Invoker<T> getInvoker() {
           return exporter.getInvoker();
       }
       public void unexport() {
        try {
            exporter.unexport();
        } catch (Throwable t) {
            logger.warn(t.getMessage(), t);
           }
           try {
            registry.unregister(registedProviderUrl);
           } catch (Throwable t) {
            logger.warn(t.getMessage(), t);
           }
           try {
            overrideListeners.remove(overrideSubscribeUrl);
            registry.unsubscribe(overrideSubscribeUrl, 
             overrideSubscribeListener);
           } catch (Throwable t) {
            logger.warn(t.getMessage(), t);
           }
       }
   };
}

dubbo提供对外服务接口

  1. 根据getProviderUrl(originInvoker) 提供者的url地址
    (dubbo://10.118.14.204:20890/com.test.ITestService?…)
  2. 并且对外提供服务protocol.export(invokerDelegete);
private <T> ExporterChangeableWrapper<T>  doLocalExport(final 
    Invoker<T> originInvoker){
    //获取到url里面的export属性:dubbo://.....
     String key = getCacheKey(originInvoker);
     ExporterChangeableWrapper<T> exporter = (ExporterChangeableWrapper<T>) 
     bounds.get(key);
     if (exporter == null) {
         synchronized (bounds) {
             exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
             if (exporter == null) {
                //getProviderUrl是获取到url里面的export属性:dubbo://.....
                 final Invoker<?> invokerDelegete = new InvokerDelegete<T>
                 (originInvoker, getProviderUrl(originInvoker));
                 //protocol是dubbo协议
                 exporter = new ExporterChangeableWrapper<T>((Exporter<T>)
                     protocol.export(invokerDelegete), originInvoker);
                 bounds.put(key, exporter);
             }
         }
     }
     return (ExporterChangeableWrapper<T>) exporter;
 }

获取Registry实例
registry://10.118.22.25:2181/com.alibaba.dubbo.registry.RegistryService?application=testservice&dubbo=2.8.4&export=dubbo://10.118.14.204:20890?com.test.ITestService?anyhost=true&application=testservice…&registry=zookeeper&timestamp=1524045346142

其中registry=zookeeper

private Registry getRegistry(final Invoker<?> originInvoker){
   URL registryUrl = originInvoker.getUrl();
   if ("registry".equals(registryUrl.getProtocol())) {
     //zookeeper
     String protocol = registryUrl.getParameter("registry", "dubbo");
       registryUrl = registryUrl.setProtocol(protocol).
       removeParameter(Constants.REGISTRY_KEY);
   }
   return registryFactory.getRegistry(registryUrl);
}

refer

1.根据注册协议获取到ZookeeperRegistry
2, 组装consume的url
3. 向zookeeper中注册消费者节点/dubbo/com.test.ITestService/consumers/consumer://
4. 订阅提供者节点/dubbo/com.test.ITestService/providers
5. 根据容错机制返回对应的Invoker

public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
    url = url.setProtocol(url.getParameter(Constants.REGISTRY_KEY, 
    Constants.DEFAULT_REGISTRY)).removeParameter(Constants.REGISTRY_KEY);
    //根据注册协议获取到ZookeeperRegistry
    Registry registry = registryFactory.getRegistry(url);
    if (RegistryService.class.equals(type)) {
        return proxyFactory.getInvoker((T) registry, type, url);
    }

    // group="a,b" or group="*" ,
    Map<String, String> qs = StringUtils.parseQueryString(
      url.getParameterAndDecoded(Constants.REFER_KEY));
    String group = qs.get(Constants.GROUP_KEY);
    if (group != null && group.length() > 0 ) {
        if ( ( Constants.COMMA_SPLIT_PATTERN.split( group ) ).length > 1
                || "*".equals( group ) ) {
            return doRefer( getMergeableCluster(), registry, type, url );
        }
    }
    return doRefer(cluster, registry, type, url);
}
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);
    /**
    组装consumer的url地址
    consumer://10.118.14.229/com.test.ITestService?application=testservice
    **/
    URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, 
      NetUtils.getLocalHost(), 0, type.getName(), 
       directory.getUrl().getParameters());

    if (! Constants.ANY_VALUE.equals(url.getServiceInterface())
            && url.getParameter(Constants.REGISTER_KEY, true)) {
        /**向zookeeper中注册节点
        /dubbo/com.test.ITestService/consumers/consumer://
        10.118.14.229/com.test.ITestService?application=testservice&category=
        consumers&check=false&default.check=false...
        **/
        registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY, 
          Constants.CONSUMERS_CATEGORY,
          Constants.CHECK_KEY, String.valueOf(false)));
    }
    /**
    订阅节点/dubbo/com.test.ITestService/providers
    一旦节点发生改变,刷新本地的invoke 具体见zookeeper那一节
    **/
    directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY, 
            Constants.PROVIDERS_CATEGORY 
            + "," + Constants.CONFIGURATORS_CATEGORY 
            + "," + Constants.ROUTERS_CATEGORY));
    return cluster.join(directory);
}

cluster
根据配置中获取cluster是failfast

MockClusterWrapper->FailfastCluster

  • MockClusterWrapper
    是cluster的装饰者模式,主要处理mock
public class MockClusterWrapper implements Cluster {
    public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
        return new MockClusterInvoker<T>(directory,
                this.cluster.join(directory));
    }
}


public class FailfastCluster implements Cluster {
    public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
        return new FailfastClusterInvoker<T>(directory);
    }
}

猜你喜欢

转载自blog.csdn.net/liyue1090041509/article/details/79991177
今日推荐