Dubbo源码解析

1 Dubbo和spring融合

1.1 Dubbo 命名空间解析

xml解析类的路径:org.apache.dubbo.config.spring.schema.DubboNamespaceHandler
public void init() {
    registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
    registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
    registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
    registerBeanDefinitionParser("config-center", new DubboBeanDefinitionParser(ConfigCenterBean.class, true));
    registerBeanDefinitionParser("metadata-report", new DubboBeanDefinitionParser(MetadataReportConfig.class, true));
    registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
    registerBeanDefinitionParser("metrics", new DubboBeanDefinitionParser(MetricsConfig.class, true));
    registerBeanDefinitionParser("ssl", new DubboBeanDefinitionParser(SslConfig.class, true));
    registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
    registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
    registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
    registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
    registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
    registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
}

可以看到服务暴露的核心bean 是 ServiceBean , 调用引用的核心bean是ReferenceBean

1.2 spring容器支持

核心类 org.apache.dubbo.config.spring.extension.SpringExtensionFactory implements ExtensionFactory
    public static void addApplicationContext(ApplicationContext context) {
        CONTEXTS.add(context);
        if (context instanceof ConfigurableApplicationContext) {
            ((ConfigurableApplicationContext) context).registerShutdownHook();
        }
    }
    public static Set<ApplicationContext> getContexts() {
        return CONTEXTS;
    }
    public <T> T getExtension(Class<T> type, String name) {

        //SPI should be get from SpiExtensionFactory
        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
            return null;
        }

        for (ApplicationContext context : CONTEXTS) {
            T bean = BeanFactoryUtils.getOptionalBean(context, name, type);
            if (bean != null) {
                return bean;
            }
        }
        return null;
    }

2 Dubbo扩展

##2.1 Java的SP实现方式

public interface IShout {
    void shout();
}
public class Dog implements IShout{
    public void shout() {
        System.out.println("dog shout");
    }
}
public class Cat implements IShout{
    public void shout() {
        System.out.println("cat shout");
    }
}
META-INFO/services/com.jd.gloabal.spi.IShout
com.jd.gloabal.spi.Dog
com.jd.gloabal.spi.Cat
public class SPIMain {
    public static void main(String[] args) {
        ServiceLoader<IShout> shouts = ServiceLoader.load(IShout.class);
        for (IShout s : shouts) {
            s.shout();
        }
    }
}
输出:
dog shout
cat shout

2.1 dubbo的SPI实现

spi 文件存储的路径再META-INFO\dubbo\internal目录下面,并且文件名为接口全路径名=接口的报名+接口名
每个spi文件里面的格式定义为 扩展名=具体的类名
dubbo=org.apache.dubbo.rpc.protocol.dubbo.DubboCountCodec

2.1.1 获取扩展实现方法

dubbo中最最核心的一个类 org.apache.dubbo.common.extension.ExtensionLoader

  通过名字获取扩展点的实现
    public T getExtension(String name) {
        return getExtension(name, true);
    }

  private T createExtension(String name, boolean wrap) {
        Class<?> clazz = getExtensionClasses().get(name)
            T instance = (T) EXTENSION_INSTANCES.get(clazz);
            if (instance == null) {
                EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
                instance = (T) EXTENSION_INSTANCES.get(clazz);
            }
            injectExtension(instance);
            if (wrap) {
                List<Class<?>> wrapperClassesList = new ArrayList<>();
                if (cachedWrapperClasses != null) {
                    wrapperClassesList.addAll(cachedWrapperClasses);
                    wrapperClassesList.sort(WrapperComparator.COMPARATOR);
                    Collections.reverse(wrapperClassesList);
                }

                if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
                    for (Class<?> wrapperClass : wrapperClassesList) {
                        Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
                        if (wrapper == null
                                || (ArrayUtils.contains(wrapper.matches(), name) && !ArrayUtils.contains(wrapper.mismatches(), name))) {
                            instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                        }
                    }
                }
            }
            initExtension(instance);
            return instance;

4 ExtensionLoader的产生,
ExtensionLoader getExtensionLoader(Class type) 就是为接口创建一个ExtensionLoader 然后缓存起来
和getAdaptiveExtension

3 Dubbo Transport 层相关

3.1 dubbo异步转同步实现方式

dubbo核心执行类
org.apache.dubbo.rpc.protocol.dubbo.DubboInvoker

boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
        int timeout = calculateTimeout(invocation, methodName);
        if (isOneway) {
            boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
            currentClient.send(inv, isSent);
            return AsyncRpcResult.newDefaultAsyncResult(invocation);
        } else {
            ExecutorService executor = getCallbackExecutor(getUrl(), inv);
            CompletableFuture<AppResponse> appResponseFuture =
                    currentClient.request(inv, timeout, executor).thenApply(obj -> (AppResponse) obj);
            // save for 2.6.x compatibility, for example, TraceFilter in Zipkin uses com.alibaba.xxx.FutureAdapter
            FutureContext.getContext().setCompatibleFuture(appResponseFuture);
            AsyncRpcResult result = new AsyncRpcResult(appResponseFuture, inv);
            result.setExecutor(executor);
            return result;
        }

3.2 客户端请求到相应过程

org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeClient

 public CompletableFuture<Object> request(Object request, int timeout, ExecutorService executor) throws RemotingException {
        return channel.request(request, timeout, executor);
    }
底层调用的是下面的channel
org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeChannel
   @Override
    public CompletableFuture<Object> request(Object request, int timeout, ExecutorService executor) throws RemotingException {   
        // create request.
        Request req = new Request();
        req.setVersion(Version.getProtocolVersion());
        req.setTwoWay(true);
        req.setData(request);
        DefaultFuture future = DefaultFuture.newFuture(channel, req, timeout, executor);
         channel.send(req);
        return future;
    }
    执行完毕则把该future 删除,同时设置返回值
```java
org.apache.dubbo.remoting.exchange.support.DefaultFuture
   public static void received(Channel channel, Response response, boolean timeout) {
        try {
            DefaultFuture future = FUTURES.remove(response.getId());
            if (future != null) {
                Timeout t = future.timeoutCheckTask;
                if (!timeout) {
                    t.cancel();
                }
                future.doReceived(response);
            } 
    }

   private void doReceived(Response res) {
        if (res.getStatus() == Response.OK) {
            this.complete(res.getResult());
        } 

判断如果是同步模式调用,则再线程中等待结果返回

org.apache.dubbo.rpc.protocol.AsyncToSyncInvoker
public Result invoke(Invocation invocation) throws RpcException {
        Result asyncResult = invoker.invoke(invocation);
            if (InvokeMode.SYNC == ((RpcInvocation) invocation).getInvokeMode()) {
                asyncResult.get(Integer.MAX_VALUE, TimeUnit.MILLISECONDS);
            }

具体调用等待线程的方法

org.apache.dubbo.rpc.AsyncRpcResult            
    @Override
    public Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        if (executor != null && executor instanceof ThreadlessExecutor) {
            ThreadlessExecutor threadlessExecutor = (ThreadlessExecutor) executor;
            threadlessExecutor.waitAndDrain();
        }
        return responseFuture.get(timeout, unit);
    }   
org.apache.dubbo.common.threadpool.ThreadlessExecutor
  public void waitAndDrain() throws InterruptedException {
        if (finished) {
            return;
        }
        Runnable runnable = queue.take();
        synchronized (lock) {
            waiting = false;
            runnable.run();
        }
        runnable = queue.poll();
        while (runnable != null) {
            try {
                runnable.run();
            } catch (Throwable t) {
                logger.info(t);
            }
            runnable = queue.poll();
        }
        finished = true;
    }   

4 服务的暴露和引用

4.1 服务暴露:

暴露路径:
ServiceBean.onApplicationEvent
->ServiceConfig.export()
  ->doExportUrls()  //里面有一个for循环,代表一个服务可以有多个通讯协议,例如tcp协议http协议,tcp是默认的协议
     ->loadRegistries(true)  //从dubbo.properties 里面组装registry的url信息
    	 ->doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) 
       		->exportLocal(URL url) 
       			->proxyFactory.getInvoker(ref ,(Class) interfaceClass , local)   dubbo会生成proxyFactory对象的扩展对象
       			 	->ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName)

1 proxyFactory : 就是为了获取一个接口的代理类,例如获取远程接口的代理
它有两个方法,代表2个作用
a, getInvoker :针对server端,将服务对象,如DemoServiceImpl 包装成Invoker对象
b getProxy 针对client端,创建接口的代理对象,例如DemoService的接口
2 Wrapper 它类似spring的BeanWrapper ,他就是包装了一个接口或一个类,可以通过Wrapper对实力对象进行访问
3 Invoker : 它是一个可执行对象,能够根据方法的名称,参数得到对应的执行结果.
它里面有一个很重要的Result Invoke(Invocation invocation), invocation是包含了需要执行的方法和参数等重要信息,目前他只有2个实现类RpcInvocation mockInvocation
它有3中类型的Invoker
(1) 本地执行类的invoker
(2) 远程通信类的Invoker
(3) 多个远程执行类的invoker聚合成集群版的Invoker

--->protocol.export
	-->Protocol$Adpative.export
		-->ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension("injvm")
		-->extension.export(arg0)
		 -->ProtocolFilterWrapper.export    
		  -->builInvokerChain //创建8个filter
		   -->injvmProtocol.export
		    ->return new InjvmExport<T>(invoker ,invoker.getUrl().getServiceKey() , exporterMap)
		     -->目的: exporterMap.put(key ,this) //key = com.alibaba.dubbo.demo.DemoService,this=InjvmExporter
		     //如果配置的不是local则暴露为远程服务(配置为local, 则表示只暴露本地服务)
		     -->proxyFactory.getInvoker  //原理和本地暴露一样都是为了获取一个Invoker对象
		     -->protoccol.export(invoker)
		     -->protocol$Adpative
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值