• dubbo工作原理


    part -- 外挂
    1.dubbo借助spring的schema启动和初始化
    1.1 spring扫描所有jar下META-INF的spring.handlers和spring.schemas。
    1.2 运行spring.handlers下定义的DubboNamespaceHandler的init方法。
    1.3 spring加载xml,执行DubboBeanDefinitionParser的parse方法,通过RootBeanDefinition将serviceBean暴露给spring。(实际调用AutowireCapableBeanFactory.registerBeanDefinition)
    1.4 serviceBean实现了BeanNameAware接口,自动注入spring中的单例name。

    part -- 服务暴露(生产者)
    2.dubbo服务暴露
    2.1 serviceBean实现了ApplicationListener,在bean初始化时触发onApplicationEvent方法,调用serviceConfig的export方法。
    2.2 serviceConfig初始化,先初始化静态变量protocol和proxyFactory。
    getExtensionLoader.getExtensionLoader ->getAdaptiveExtension->createAdaptiveExtension->getAdaptiveExtensionClass->getExtensionClasses->loadExtensionClasses
    ->loadFile->createAdaptiveExtensionClassCode
    loadFile采用的是java spi的思想,分别读取META-INF/services/,META-INF/dubbo/,META-INF/dubbo/internal/下文件进行解析。
    以protocol为例,其中ProtocolFilterWrapper和ProtocolListenerWrapper是有参数为protocol构造函数的,被放到Set<Class<?>> cachedWrapperClasses(后面会用到)中。
    没有protocol构造函数,但是有@Adaptive注解的,被放到Holder<Object> cachedAdaptiveInstance中。
    以上都不满足的放到cachedClasses中。
    createAdaptiveExtensionClassCode通过javassist字节码技术生成代理类Protocol$Adpative,ProxyFactory$Adpative。
    附上两个动态类的源码。可以看到protocol默认的是dubbo,proxy默认的是javassist。
    2.3 export判断是否需要延迟暴露,执行暴露方法doExport()。
    2.4 doExport检查通过,调用doExportUrls
    2.5 doExportUrls根据不同的协议将服务以URL(dubbo)形式暴露。
    2.6 如果服务未配置成remote,则本地暴露(exportLocal),如果未配置成local,则注册服务(registryProtocol)
    2.7 exportLocal:生成本地protocol(Constants.LOCAL_PROTOCOL = injvm),
    proxyFactory.getInvoker StubProxyFactoryWrapper->JavassistProxyFactory.getInvoker。Wrapper.getWrappery获取服务的封装代理类(javassist动态字节码),详细参照ClassGenerator.toClass。
    protocol.export ExtensionLoader.getExtension(injvm)->createExtension -> getExtensionClasses(返回cachedClasses对应的值)
    接着循环cachedWrapperClasses,层层装饰(装饰模式),InjvmProtocol,ProtocolFilterWrapper,ProtocolListenerWrapper增强服务。
    ProtocolFilterWrapper buildInvokerChain建立了filter链,方便开发者根据业务进行扩展。
    registryProtocol export ->ProtocolFilterWrapper export-> ProtocolListenerWrapper export->dubboProtocol export。

    3.netty启动
    3.1 openServer netty server打开侦听服务,并缓存服务。
    dubbo -> export() -> openServer() -> createServer() -> Exchangers.bind()(HeaderExchanger) -> NettyTransporter -> NettyServer.open()(编码解码采用exchange)
    netty ChannelFactory(boss worker) ChannelPipeline(责任链模式) ChannelHandler(处理器) --- 反应器模式

    part -- 服务引用(消费者)
    4.dubbo服务引用
    4.1 referenceBean实现了InitializingBean接口,在afterPropertiesSet后执行getObject()方法,调用referenceConfig的init方法。
    4.2 StaticContext.getSystemContext()是dubbo全局的线程安全上下文,存放方法调用的相关信息。
    4.2 createProxy,设置invoker,这里的invoker有协议默认的dubbo invoker,cluster invoker(重连机制,默认Failover,重试两次,一共三次)
    返回InvokerInvocationHandler(javassist动态字节码改造后的代理,执行方法时,实际执行的是invoker的doinvoke方法)
    cluster invoker的doinvoke方法会调用select(),负载均衡,默认RandomLoadBalance
    4.3 获取dubbo invoker时,调用dubbo的refer,调用getClients获取ExchangeClient,默认的ExchangeClient是共享的getSharedClient。initClient默认是非延迟的,调用Exchangers.connect,最终调用HeaderExchanger.connect,调用
    Transporters.connect,同生产者一样,默认的Transporters是netty。因此最终的ExchangeClient是NettyClient。
    4.3 dubbo invoker doinvoke方法,ExchangeClient.request方法,结果通过future的get方法返回,get方法通过lock+while+超时控制。
    4.4 ExchageClient.request最终调用的是nettyChannel
    1.NettyHandler.messageReceived(ChannelHandlerContext ctx, MessageEvent e)
    2.AbstractPeer.received(Channel ch, Object msg)
    3.MultiMessageHandler.received(Channel channel, Object message)
    4.AllChannelHandler.received(Channel channel, Object message)
    5.DecodeHandler.received(Channel channel, Object message)
    6.HeaderExchangeHandler.received(Channel channel, Object message)
    7.DefaultFuture.received(Channel channel, Response response) //注意是static方法
    DefaultFuture future = FUTURES.remove(response.getId());
    if (future != null) {
    future.doReceived(response);
    }

    http://blog.csdn.net/a19881029/article/details/51058428

    spring
    1. 入口ContextLoaderListener监听器,调用contextInitialized方法,ContextLoder的initWebApplicationContext,createWebApplicationContext默认创建ContextLoader.properties里的XmlWebApplicationContext,强制转换成configureAndRefreshWebApplicationContext
    最终调用AbstractApplicationContext的refresh方法(前面调用了ApplicationContextInitializer的initialize,这里可以做一些spring默认规则的修改,比如id重复bean处理,spring默认覆盖)
    2.

     动态生成的Protocol$Adpative.class

    package com.alibaba.dubbo.rpc;
    
    import com.alibaba.dubbo.common.extension.ExtensionLoader;
    
    public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {
        public void destroy() {
            throw new UnsupportedOperationException(
                    "method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
        }
    
        public int getDefaultPort() {
            throw new UnsupportedOperationException(
                    "method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
        }
    
        public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1)
                throws java.lang.Class {
            if (arg1 == null)
                throw new IllegalArgumentException("url == null");
            com.alibaba.dubbo.common.URL url = arg1;
            String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
            if (extName == null)
                throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url("
                        + url.toString() + ") use keys([protocol])");
            com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader
                    .getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
            return extension.refer(arg0, arg1);
        }
    
        public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0)
                throws com.alibaba.dubbo.rpc.Invoker {
            if (arg0 == null)
                throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
            if (arg0.getUrl() == null)
                throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
            com.alibaba.dubbo.common.URL url = arg0.getUrl();
            String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
            if (extName == null)
                throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url("
                        + url.toString() + ") use keys([protocol])");
            com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader
                    .getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
            return extension.export(arg0);
        }
    }
    View Code

    动态生成的ProxyFactory$Adpative.class

    package com.alibaba.dubbo.rpc;
    
    import com.alibaba.dubbo.common.extension.ExtensionLoader;
    
    public class ProxyFactory$Adpative implements com.alibaba.dubbo.rpc.ProxyFactory {
        public java.lang.Object getProxy(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.Invoker {
            if (arg0 == null)
                throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
            if (arg0.getUrl() == null)
                throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
            com.alibaba.dubbo.common.URL url = arg0.getUrl();
            String extName = url.getParameter("proxy", "javassist");
            if (extName == null)
                throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url("
                        + url.toString() + ") use keys([proxy])");
            com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader
                    .getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);
            return extension.getProxy(arg0);
        }
    
        public com.alibaba.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1,
                com.alibaba.dubbo.common.URL arg2) throws java.lang.Object {
            if (arg2 == null)
                throw new IllegalArgumentException("url == null");
            com.alibaba.dubbo.common.URL url = arg2;
            String extName = url.getParameter("proxy", "javassist");
            if (extName == null)
                throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url("
                        + url.toString() + ") use keys([proxy])");
            com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader
                    .getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);
            return extension.getInvoker(arg0, arg1, arg2);
        }
    }
    
    
    {class com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory@5d1275be, class com.alibaba.dubbo.common.compiler.support.JavassistCompiler=com.alibaba.dubbo.common.compiler.support.JavassistCompiler@66f03cae, class com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory@261ff84e}
    
    injvm://127.0.0.1/com.ihome.tf.order.service.IBenefitFoundService?anyhost=true&application=tf-order&default.retries=0&default.timeout=10000&dubbo=2.5.3&interface=com.ihome.tf.order.service.IBenefitFoundService&methods=update,clear,qryBenefitFndOrderList,qryCheckPassedBenefitList,qryBenefitFoundOrderSumInf,verify,qryBenefitFound&owner=tf&pid=1492&revision=0.0.1-SNAPSHOT&side=provider&timestamp=1457518110700
    View Code

    动态生成的Wrapper1.class

    package com.alibaba.dubbo.common.bytecode;
    
    import com.prepay.dto.ShareRulesReq;
    import com.prepay.service.IOutShareService;
    import java.lang.reflect.InvocationTargetException;
    import java.util.Map;
    
    public class Wrapper1 extends Wrapper
      implements ClassGenerator.DC
    {
      public static String[] pns;
      public static Map pts;
      public static String[] mns;
      public static String[] dmns;
      public static Class[] mts0;
      public static Class[] mts1;
      public static Class[] mts2;
    
      public String[] getPropertyNames()
      {
        return pns;
      }
    
      public boolean hasProperty(String paramString)
      {
        return jdField_pts_of_type_JavaUtilMap.containsKey(paramString);
      }
    
      public Class getPropertyType(String paramString)
      {
        return (Class)jdField_pts_of_type_JavaUtilMap.get(paramString);
      }
    
      public String[] getMethodNames()
      {
        return mns;
      }
    
      public String[] getDeclaredMethodNames()
      {
        return dmns;
      }
    
      public void setPropertyValue(Object paramObject1, String paramString, Object paramObject2)
      {
        try
        {
          IOutShareService localIOutShareService = (IOutShareService)paramObject1;
        }
        catch (Throwable localThrowable)
        {
          throw new IllegalArgumentException(localThrowable);
        }
        throw new NoSuchPropertyException("Not found property "" + paramString + "" filed or setter method in class com.ihome.prepay.service.IOutShareService.");
      }
    
      public Object getPropertyValue(Object paramObject, String paramString)
      {
        try
        {
          IOutShareService localIOutShareService = (IOutShareService)paramObject;
        }
        catch (Throwable localThrowable)
        {
          throw new IllegalArgumentException(localThrowable);
        }
        throw new NoSuchPropertyException("Not found property "" + paramString + "" filed or setter method in class com.ihome.prepay.service.IOutShareService.");
      }
    
      public Object invokeMethod(Object paramObject, String paramString, Class[] paramArrayOfClass, Object[] paramArrayOfObject)
        throws InvocationTargetException
      {
        IOutShareService localIOutShareService;
        try
        {
          localIOutShareService = (IOutShareService)paramObject;
        }
        catch (Throwable localThrowable1)
        {
          throw new IllegalArgumentException(localThrowable1);
        }
        try
        {
          if ((!"queryShareRuleDetail".equals(paramString)) || (paramArrayOfClass.length == 1))
            return localIOutShareService.queryShareRuleDetail((String)paramArrayOfObject[0]);
          if ((!"queryShareRuleList".equals(paramString)) || (paramArrayOfClass.length == 1))
            return localIOutShareService.queryShareRuleList((ShareRulesReq)paramArrayOfObject[0]);
          if ((!"querySharePullDownList".equals(paramString)) || (paramArrayOfClass.length == 0))
            return localIOutShareService.querySharePullDownList();
        }
        catch (Throwable localThrowable2)
        {
          throw new InvocationTargetException(localThrowable2);
        }
        throw new NoSuchMethodException("Not found method "" + paramString + "" in class com.ihome.prepay.service.IOutShareService.");
      }
    }
    View Code

    <以上内容由同事提供>

      

    如果想了解更多Dubbo源码的知识,请移步 Dubbo源码解读——通向高手之路 的视频讲解:
    http://edu.51cto.com/sd/2e565
  • 相关阅读:
    canvas和svg
    表单控件及表单属性
    ajax
    数据结构与算法经典问题解析-Java语言描述
    SpringBoot
    ThreadLocal 原理
    代理模式-结构型
    框架面试
    Hash算法总结
    集合与多线程面试
  • 原文地址:https://www.cnblogs.com/kevin-yuan/p/5531261.html
Copyright © 2020-2023  润新知