Dubbo源码简单分析

一、创建代理

1.1、registry、consumer等配置信息通过spring初始化,比如DubboNamespaceHandler
1.2、创建代理对象的时候,通过registry配置连接zookeeper注册并获取provider信息

ReferenceBean.getObject()
->return get();    --ReferenceBean
  ->init();
    ->map存放了registry、application等
    ->ref = createProxy(map);
      ->List<URL> us = loadRegistries(false);
        ->List<URL> registryList = new ArrayList<URL>();
        ->for (RegistryConfig config : registries)
           ->url = url.setProtocol(Constants.REGISTRY_PROTOCOL);  //protocol是registry
          ->registryList.add(url);
        ->return registryList;
      ->for (URL u : us)
        ->urls.add(u.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
      ->URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME); 
      ->List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
      ->for (URL url : urls)  --ReferenceConfig
        ->invokers.add(refprotocol.refer(interfaceClass, url));  --url来自上面的loadRegistries(false)【ReferenceConfig.java】
          ->RegistryProtocol.refer(Class<T> type, URL url)
            ->Registry registry = registryFactory.getRegistry(url);
            ->return doRefer(cluster, registry, type, url);
                ->RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
                ->directory.setRegistry(registry);
                ->directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY, ...
                  ->registry.subscribe(url, this);    --registry是ZookeeperRegistry 
                ->return cluster.join(directory);   --cluster是FailoverCluster 
                  ->return new FailoverClusterInvoker<T>(directory);
      ->URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME); 
      ->invoker = cluster.join(new StaticDirectory(u, invokers));   //将多个注册中心的invokers合并成一个invoker 
     ->return (T) proxyFactory.getProxy(invoker);
        ->return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
  ->ref;
二、通过zookeeper订阅并获取服务

2.1、registry.subscribe(url, this)订阅zookeeper后,notify返回服务提供者的具体信息
2.2、为每个服务提供者创建DubboInvoker,如果connections=0,共享NettyClient

public synchronized void notify(List<URL> urls)    --RegistryDirectory.java,继承NotifyListener
->for (URL url : urls)
  ->invokerUrls.add(url);
->refreshInvoker(invokerUrls);
  ->Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(invokerUrls) ;// 将URL列表转成Invoker列表
  
/* ====================================注册DubboInvoker_S ===========================================*/
    ->invoker = new InvokerDelegete<T>(protocol.refer(serviceType, url), url, providerUrl);   --protocol是DubboProtocol
      ->DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
        ->private ExchangeClient[] getClients(URL url)
          ->ExchangeClient[] clients = new ExchangeClient[connections];
          ->clients[i] = initClient(url);
           ->return Exchangers.connect(url ,requestHandler);
      ->return invoker;
    ->newUrlInvokerMap.put(key, invoker);
/* ====================================注册DubboInvoker_E ===========================================*/

  ->Map<String, List<Invoker<T>>> newMethodInvokerMap = toMethodInvokers(newUrlInvokerMap); // 换方法名映射Invoker列表
    ->for (Invoker<T> invoker : invokersMap.values())
      ->List<Invoker<T>> methodInvokers = newMethodInvokerMap.get(method);
      ->methodInvokers.add(invoker);
  ->this.methodInvokerMap = multiGroup ? toMergeMethodInvokerMap(newMethodInvokerMap) : newMethodInvokerMap;
  ->this.urlInvokerMap = newUrlInvokerMap;
三、通过Netty调用服务

3.1、调用DubboInvoker远程访问,request和response的body中会有一个id,网络请求本身是共享并非阻塞的,采用Future默认控制同步还是异步返回结果

InvokerInvocationHandler.invoke(Object proxy, Method method, Object[] args)
->return invoker.invoke(new RpcInvocation(method, args)).recreate();    --invoker假设是FailoverClusterInvoker
/* ====================================Directory_获取有效的invokers_S ===========================================*/
  ->List<Invoker<T>> invokers = list(invocation);
    ->return directory.list(invocation);   //directory是RegistryDirectory【AbstractClusterInvoker】
      ->List<Invoker<T>> invokers = doList(invocation);  --AbstractDirectory
        ->invokers = localMethodInvokerMap.get(methodName);  --RegistryDirectory
      ->invokers = router.route(invokers, getConsumerUrl(), invocation);
        ->return getNormalInvokers(invokers);   --MockInvokersSelector
/* ====================================Directory_获取有效的invokers_E ===========================================*/

/* ====================================LoadBalance_通过算法取其中一个invoker _S ===========================================*/
  ->loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl().getMethodParameter(invocation.getMethodName(),Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE));
  ->return doInvoke(invocation, invokers, loadbalance);  --doInvoke在FailoverClusterInvoker
    ->for (int i = 0; i < len; i++)
      ->Invoker<T> invoker = select(loadbalance, invocation, copyinvokers, invoked);
/* ====================================LoadBalance_通过算法取其中一个invoker _E ===========================================*/

/* ====================================DubboInvoker调用_S ===========================================*/
      ->Result result = invoker.invoke(invocation);   --假设invoker是DubboInvoker
        ->return doInvoke(invocation);   --【AbstractInvoker.java】
          ->currentClient = clients[index.getAndIncrement() % clients.length];
    ====采用异步方式,调用远程服务
            ->if (isAsync)
              ->ResponseFuture future = currentClient.request(inv, timeout) ;
              ->RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));
              ->return new RpcResult();
    ====采用同步方式,调用远程服务
            ->else
              ->return (Result) currentClient.request(inv, timeout).get();
                ->.request(inv, timeout)
                  ->Request req = new Request();
                  ->req.setData(request);
                  ->DefaultFuture future = new DefaultFuture(channel, req, timeout);
                  ->channel.send(req);
                  ->return future;
                ->.get()
                  ->return get(timeout);   --DefaultFuture
                    ->done.await(timeout, TimeUnit.MILLISECONDS);   --DefaultFuture
                    ->return returnFromResponse();   --DefaultFuture
                      ->return res.getResult();   --DefaultFuture
        ->return result;
/* ====================================DubboInvoker调用_E ===========================================*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值