文档章节

dubbo工作原理

 快鸟
发布于 2017/05/08 12:40
字数 1503
阅读 11
收藏 0
点赞 0
评论 0

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

 

 

<以上内容由同事提供>

本文转载自:http://www.cnblogs.com/kevin-yuan/p/5531261.html

共有 人打赏支持
粉丝 0
博文 2
码字总数 0
作品 0
深圳
dubbo源码解析-简单原理、与spring融合

前言 结束了和这两个小专题之后,有朋友问我什么时候开始,本篇为的启蒙篇.之前是一直和大家一起看源码,鉴于,所以本篇将和大家一起写写代码. 插播面试题 dubbo的原理是怎么样的?请简单谈谈 有没...

肥朝 ⋅ 2017/12/16 ⋅ 0

自建zookeeper测试dubbo

Zookeeper 起因:由于我们现在都是拆分的微服务,因此dubbo debug就需要跨多个微服务。现有解决办法是在dubbo admin控制台,将其他服务提供者关闭,只保留本机服务提供者。但是这种方式会影响...

yushiwh ⋅ 2017/06/27 ⋅ 0

有经验JAVA程序员如何提升自己?

具有一到五年开发经验 需要学习内容很多 JVM/分布式/高并发/性能优化/Spring MVC/Spring Boot/Spring Cloud/MyBatis/Netty源码分析等等等 01、透彻理解Tomcat原理手写动静态资源的实现 02、分...

阿阳啊啊 ⋅ 2017/11/29 ⋅ 0

百度、阿里、腾讯、京东、大型互联网分布式架构必备技能

分布式架构 迎接高并发大数据的挑战,从深度到广度完善知识体系,成为下一个互联网高薪人才。 理论结合实战,透彻理解分布式架构及其解决方案。 面向人群 1、工作1-5年需要突破瓶颈; 2、传统...

Java高级架构 ⋅ 2017/12/21 ⋅ 0

dubbo 视频教程

深度解剖dubbo源码 为什么要学习dubbo 源码? 1.如果你想深入学习SOA的微服务架构设计,那通过读dubbo源码是一条非常不错的通往SOA架构设计之路,毕竟SOA的服务治理就是dubbo首先提出来的,比...

qq594295b3c16b8 ⋅ 2017/06/16 ⋅ 0

dubbo管理控制台安装和使用

一、概述 Dubbo 是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。 主要核心部件: Remoting: 网络通信框...

hanfeng ⋅ 2015/11/03 ⋅ 0

架构设计:系统间通信(45)——阶段性问题记录

到此为止 《架构设计:系统间通信》专题就暂时告一段落了。这边文章笔者用于暂时记录这个专题中还需要补充的内容,并在后续的整理中足一补上: 退避算法和退避规则,以及其应用场景 系统间通...

yinwenjie ⋅ 2016/08/11 ⋅ 0

dubbo “插入”到spring框架

作为一个分布式服务治理框架,dubbo做的非常好,在业界使用很广,所以最近研究了下这个框架。任何框架要研究其原理最好的办法之一就是沿着其运行流 程进行追踪,这样就能从上到下,从粗到细对...

squanchao ⋅ 2015/10/29 ⋅ 0

架构师必备词汇和知识点

01 高可用 负载均衡(负载均衡算法) 反向代理 服务隔离 服务限流 服务降级(自动优雅降级) 失效转移 超时重试(代理超时、容器超时、前端超时、中间件超时、数据库超时、NoSql超时) 回滚机...

t4i2b10X4c22nF6A ⋅ 2017/11/24 ⋅ 0

某宝某团队的题目

hashmap为什么线程不安全, java.concurrent包的常用使用 spring如何进行bean的管理 tomcat常用的gc算法,如何配置 jvm内存模型 http请求的完整流程 从dns到三次握手到最后到action,以及htt...

明舞 ⋅ 2015/08/31 ⋅ 3

没有更多内容

加载失败,请刷新页面

加载更多

下一页

用ZBLOG2.3博客写读书笔记网站能创造今日头条的辉煌吗?

最近两年,著名的自媒体网站今日头条可以说是火得一塌糊涂,虽然从目前来看也遇到了一点瓶颈,毕竟发展到了一定的规模,继续增长就更加难了,但如今的今日头条规模和流量已经非常大了。 我们...

原创小博客 ⋅ 37分钟前 ⋅ 0

MyBatis四大核心概念

本文讲解 MyBatis 四大核心概念(SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession、Mapper)。 MyBatis 作为互联网数据库映射工具界的“上古神器”,训有四大“神兽”,谓之:Sql...

waylau ⋅ 57分钟前 ⋅ 0

以太坊java开发包web3j简介

web3j(org.web3j)是Java版本的以太坊JSON RPC接口协议封装实现,如果需要将你的Java应用或安卓应用接入以太坊,或者希望用java开发一个钱包应用,那么用web3j就对了。 web3j的功能相当完整...

汇智网教程 ⋅ 今天 ⋅ 0

2个线程交替打印100以内的数字

重点提示: 线程的本质上只是一个壳子,真正的逻辑其实在“竞态条件”中。 举个例子,比如本题中的打印,那么在竞态条件中,我只需要一个方法即可; 假如我的需求是2个线程,一个+1,一个-1,...

Germmy ⋅ 今天 ⋅ 0

Springboot2 之 Spring Data Redis 实现消息队列——发布/订阅模式

一般来说,消息队列有两种场景,一种是发布者订阅者模式,一种是生产者消费者模式,这里利用redis消息“发布/订阅”来简单实现订阅者模式。 实现之前先过过 redis 发布订阅的一些基础概念和操...

Simonton ⋅ 今天 ⋅ 0

error:Could not find gradle

一.更新Android Studio后打开Project,报如下错误: Error: Could not find com.android.tools.build:gradle:2.2.1. Searched in the following locations: file:/D:/software/android/andro......

Yao--靠自己 ⋅ 昨天 ⋅ 0

Spring boot 项目打包及引入本地jar包

Spring Boot 项目打包以及引入本地Jar包 [TOC] 上篇文章提到 Maven 项目添加本地jar包的三种方式 ,本篇文章记录下在实际项目中的应用。 spring boot 打包方式 我们知道,传统应用可以将程序...

Os_yxguang ⋅ 昨天 ⋅ 0

常见数据结构(二)-树(二叉树,红黑树,B树)

本文介绍数据结构中几种常见的树:二分查找树,2-3树,红黑树,B树 写在前面 本文所有图片均截图自coursera上普林斯顿的课程《Algorithms, Part I》中的Slides 相关命题的证明可参考《算法(第...

浮躁的码农 ⋅ 昨天 ⋅ 0

android -------- 混淆打包报错 (warning - InnerClass ...)

最近做Android混淆打包遇到一些问题,Android Sdutio 3.1 版本打包的 错误如下: Android studio warning - InnerClass annotations are missing corresponding EnclosingMember annotation......

切切歆语 ⋅ 昨天 ⋅ 0

eclipse酷炫大法之设置主题、皮肤

eclipse酷炫大法 目前两款不错的eclipse 1.系统设置 Window->Preferences->General->Appearance 2.Eclipse Marketplace下载【推荐】 Help->Eclipse Marketplace->搜索‘theme’进行安装 比如......

anlve ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部