一、服务发布 - 原理:

首先看Dubbo日志,截取重要部分:

  1)暴露本地服务

    

  1. Export dubbo service com.alibaba.dubbo.demo.DemoService to local registry, dubbo version: 2.0.0, current host: 10.165.2.47

  2)暴露远程服务

    

  1. Export dubbo service com.alibaba.dubbo.demo.DemoService to url dubbo://10.165.2.47:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&bind.ip=10.165.2.47&bind.port=20880&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=3880&qos.port=22222&side=provider&timestamp=1520303067433, dubbo version: 2.0.0, current host: 10.165.2.47
  2.  
  3. Register dubbo service com.alibaba.dubbo.demo.DemoService url dubbo://10.165.2.47:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&bind.ip=10.165.2.47&bind.port=20880&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=3880&qos.port=22222&side=provider&timestamp=1520303067433 to registry registry://224.5.6.7:1234/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&dubbo=2.0.0&pid=3880&qos.port=22222&registry=multicast&timestamp=1520303067418, dubbo version: 2.0.0, current host: 10.165.2.47

  3)启动Netty

     

  1. Start NettyServer bind /0.0.0.0:20880, export /10.165.2.47:20880, dubbo version: 2.0.0, current host: 10.165.2.47

  4)打开Zookeeper

    

  1. INFO zookeeper.ClientCnxn: Opening socket connection to server /192.168.48.117:2181

  5)注册到Zookeeper

    

  1. Register: dubbo://10.165.2.47:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=3880&side=provider&timestamp=1520303067433, dubbo version: 2.0.0, current host: 10.165.2.47

  6)监听Zookeeper

    

  1. Subscribe: provider://10.165.2.47:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=3880&side=provider&timestamp=1520303067433, dubbo version: 2.0.0, current host: 10.165.2.47

  7)频繁发送广播包,注册中心利用广播包监听provider健康状况

  1. [DUBBO] Send broadcast message: subscribe provider://10.165.2.47:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=3880&side=provider&timestamp=1520303067433 to /224.5.6.7:1234, dubbo version: 2.0.0, current host: 10.165.2.47
  2.  
  3. [DUBBO] Receive multicast message: subscribe provider://10.165.2.47:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=3880&side=provider&timestamp=1520303067433 from /10.165.2.47:1234, dubbo version: 2.0.0, current host: 10.165.2.47

二、根据原理分析源码

  1)首先看Provider注册文件:

    

  1. <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
  2.  
  3. <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>

    可以看到,是通过dubbo的schema service进行注入的,那我们找到DubboNameSpaceHandler,Dubbo命名空间处理器,找到<dubbo:service>标签解析行:

  1. public void init() {
  2. registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
  3. registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
  4. registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
  5. registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
  6. registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
  7. registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
  8. registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
  9. //这里就是<dubbo:service>标签的解析注入入口
  10. registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
  11. registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
  12. registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
  13. }

  

  2)上面new DubboBeanDefinitionParser是<dubbo:service>解析注入入口,那ServiceBean.class就是<dubbo:service>标签的发布订阅入口,进入ServiceBean可以看到一个核心方法onApplicationEvent(),其中export()就是发布方法:

   

  1. public void onApplicationEvent(ContextRefreshedEvent event) {
  2. if (isDelay() && !isExported() && !isUnexported()) {
  3. if (logger.isInfoEnabled()) {
  4. logger.info("The service ready on spring started. service: " + getInterface());
  5. }
  6. //这里是发布方法
  7. export();
  8. }
  9. }

  3)发布代码处理路径

  

  1. ServiceBean.onApplicationEvent
  2. -->export()
  3. -->ServiceConfig.export()
  4. -->doExport()
  5. -->doExportUrls() //里面有个for循环,代表一个服务可以有多个通信协议,例如tcp、http、dubbo等协议,默认是tcp协议
  6. -->loadRegistries(true) //加载注册信息,组装注册中心url信息,如源码中config.properties中读取dubbo.registry.address = zookeeper://192.168.99.100:32770链接信息,组装Provider注册链接串
  7. -->doExportUrlsFor1Protocol(protocolConfig, registryURLs)
                  // export to local if the config is not remote (export to remote only when config is remote)远程暴露
  1.               -->exportLocal(url)
                    -->proxyFactory.getInvoker(ref, (Class) interfaceClass, local))
                      -->ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension("javassist");
                      -->extension.getInvoker(arg0, arg1, arg2)
                        -->StubProxyFactoryWrapper.getInvoker(T proxy, Class<T> type, URL url)
                          -->proxyFactory.getInvoker(proxy, type, url)
                            -->JavassistProxyFactory.getInvoker(T proxy, Class<T> type, URL url)
                              -->Wrapper.getWrapper(com.alibaba.dubbo.demo.provider.DemoServiceImpl)
                                -->makeWrapper(Class<?> c)
                              -->return new AbstractProxyInvoker<T>(proxy, type, url)
                  -->protocal.export //本地暴露
                    -->Protocal$Adaptive.export
                      -->ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocal.class).getExtension("injvm");
                      -->extension.export(arg0)
                        -->ProtocalFilterWrapper.export
                           -->buildInvokerChain //创建8个Filter
                            -->ProtocalListenerWrapper.export
                              -->InjvmProtocal.export
                                -->return new InjvmExporter
  1.                                -->InjvmExporter(Invoker<T> invoker, String key, Map<String, Exporter<?>> exporterMap) {super(invoker);
  1.                                   this.key = key;
                                      this.exporterMap = exporterMap;
                                      exporterMap.put(key, this); //key=com.alibaba.dubbo.demo.DemoService this=InjvmExporter
                                     }
  2.               // export to local if the config is not remote (export to remote only when config is remote)远程暴露
                  -->proxyFactory.getInvoker()原理和本地暴露一样都是为了获取一个Invoker对象
                    -->protocal.export
                      -->Protocal$Adaptive.ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocal.class).getExtension("register");
                      -->extension.export(arg0)
                        -->ProtocalFilterWrappter.export
                          -->ProtocalListenerWrapper.export
                            -->RegistryProtocal.export
                              -->doLocalExport(originInvoker)
                                -->getCacheKey(originInvoker) //读取dubbo://192.168.100.51:20880/
                                -->protocal.export
                                  -->Protocol$Adaptive.export
                                    -->ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocl.class).getExtension("dubbo");
                                    -->extension.export(arg0)
                                      -->ProtocolFilterWrapper.export
                                        -->buildInvokerChain//创建8个Filter
                                         -->ProtocalListenerWrapper.export
                    -------1netty服务暴露的开始-------- -->DubboProtocal.export
                                            -->serviceKey(url) //组装key=com.alibaba.dubbo.demo.DemoService:20880
                                            -->目的:exporterMap.put(key, this); //key=com.alibaba.dubbo.demo.DemoService:20880 this=
                                            -->openServer(url)
                                              -->createServer(url)
                    --------2、信息交换层exchange 开始--------     -->Exchanges.bind(url, requestHandler) //exchanger是一个信息交换层
                                                  -->getExchanger(url)
                                                    -->getExchange(type)
                                                      -->ExtensionLoader.getExtensionLoader(Exchanger.class).getExtension("header")
                                                        -->HeaderExchanger.bind
                                                          -->Transporters.bind(url, new DecoderHandler(new HeaderExchangeHandler(handler)))
                                                            -->new HeaderExchangeHandler(handler) //this.handler = handler
                                                              -->
    new DecoderHandler
                                                                -->new AbstractChannelHandlerDelegate //this.handler = handler;
                    ------------>3、网络传输层 transporter ------------          -->Transporters.bind
                                                                -->getTransporter
                                                                  -->
    ExtensionLoader.getExtensionLoader(Transporter.class).getAdaptiveExtension();
                                                                -->Transporter$Adaptive.bind
                                                                    //netty服务暴露
                                                                  -->ExtensionLoader.getExtensionLoader(com.alibaba.remoting.Transporter.class).getExtension("netty")
                                                                  -->extension.bind(arg0, arg1)
                                                                    -->NettyTransporter.bind
                                                                      -->new NettyServer(url, listener)
                                                                        -->AbstractPeer //this.url = url; this.handler = handler;
                                                                        -->AbstractEndpoint //codec timeout=1000 connectTimeout=3000
                                                                        -->AbstractServer //bindAddress accepts=0 idleTimeout=600000
                    ----------->4、打开端口,暴露netty服务 --------------                      -->doOpen()
                                                                          -->设置NioServerSocketChannelFactory boss worker的线程池 线程个数为3
                                                                          -->设置编码handler
                                                                          -->bootstrap.bind(getBindAddress())
                                                                -->new HeaderExchangeServer()
                                                                  -->this.server = NettyServer
                                                                  -->this.heartbeat=600000
                                                                  -->heartbeatTimeout=180000
                                                                  -->startHeatbeatTimer() //这是一个心跳定时器,采用线程池ScheduledExecutePool,如果断开了就心跳重连
                                                                    -->
  1.                                                                 
                                                                   
                       
  1.  
  1.  
  1.   
  1.  
  2. 说说上述这些类及方法的概念作用:”
      1proxyFactory:就是为了获取一个接口的代理类,例如获取一个远程接口的代理。
      它有2个方法,代表2个作用
        agetInvoker:针对server端,将服务对象,例如DemoServiceImpl包装成一个Wrapper对象。
        bgetProxy:针对client端,创建接口的代理对象,例如DemoService的接口。
  3.  
  4.   2makeWrapper:它类似springBeanWrapper,它就是包装了一个接口或一个类,可以通过Wrapper对实例对象进行赋值取值以及指定方法的调用。
  5.  
  6.   3Invoker:它是一个可执行的对象,能够根据方法名称、参数得到相应的执行结果。
        它里面有一个很重要的方法Result invoke(Invocation invocation),Invocation是包含了需要执行的方法和参数的重要信息,目前它只有2个实现类RpcInvocation MockInvocation
        它有3种类型的Invoker
          1、本地执行类的Invoker
          2、远程通信类的Invoker
          3、多个远程通信执行类的Invoker聚合成集群版的Invoker
      4Protocol
        1export暴露远程服务(用语服务端),就是将proxyFactory.getInvoker创建的代理类invoker对象,通过协议暴露给外部。
        2refer:引用远程服务(用于客户端)
      
      5Exporter:维护invoker的生命周期
  7.  
  8.   6exchanger:信息交换层,封装请求响应模式同步转异步
  9.  
  10.   7transporter:网络传输层,用来抽象Nettydubbo默认)或者Mina的统一接口

  4)暴露本地服务与暴露远程服务的区别是什么?

    a、暴露本地服务:指暴露在同一个JVM里面,不用通过zk来进行远程通信,例如在同一个服务里面(tomcat),自己调用自己的接口,就无需进行网络IP连接通信。

    b、暴露远程服务:指暴露给远程客户端的IP和端口号,通过网络来实现通信。

2、Dubbo源码解析--服务发布原理(Netty服务暴露)的更多相关文章

  1. dubbo源码解析五 --- 集群容错架构设计与原理分析

    欢迎来我的 Star Followers 后期后继续更新Dubbo别的文章 Dubbo 源码分析系列之一环境搭建 博客园 Dubbo 入门之二 --- 项目结构解析 博客园 Dubbo 源码分析系列之 ...

  2. dubbo源码解析-zookeeper创建节点

    前言 在之前dubbo源码解析-本地暴露中的前言部分提到了两道高频的面试题,其中一道dubbo中zookeeper做注册中心,如果注册中心集群都挂掉,那发布者和订阅者还能通信吗?在上周的dubbo源码 ...

  3. Dubbo 源码解析四 —— 负载均衡LoadBalance

    欢迎来我的 Star Followers 后期后继续更新Dubbo别的文章 Dubbo 源码分析系列之一环境搭建 Dubbo 入门之二 --- 项目结构解析 Dubbo 源码分析系列之三 -- 架构原 ...

  4. dubbo源码解析-spi(4)

    前言 本篇是spi的第四篇,本篇讲解的是spi中增加的AOP,还是和上一篇一样,我们先从大家熟悉的spring引出AOP. AOP是老生常谈的话题了,思想都不会是一蹴而就的.比如架构设计从All in ...

  5. dubbo源码解析-spi(一)

    前言 虽然标题是dubbo源码解析,但是本篇并不会出现dubbo的源码,本篇和之前的dubbo源码解析-简单原理.与spring融合一样,为dubbo源码解析专题的知识预热篇. 插播面试题 你是否了解 ...

  6. Dubbo源码学习--优雅停机原理及在SpringBoot中遇到的问题

    Dubbo源码学习--优雅停机原理及在SpringBoot中遇到的问题 相关文章: Dubbo源码学习文章目录 前言 主要是前一阵子换了工作,第一个任务就是解决目前团队在 Dubbo 停机时产生的问题 ...

  7. dubbo源码解析-spi(3)

    前言 在上一篇的末尾,我们提到了dubbo的spi中增加了IoC和AOP的功能.那么本篇就讲一下这个增加的IoC,spi部分预计会有四篇,因为这东西实在是太重要了.温故而知新,我们先来回顾一下,我们之 ...

  8. 顺序线性表 ---- ArrayList 源码解析及实现原理分析

    原创播客,如需转载请注明出处.原文地址:http://www.cnblogs.com/crawl/p/7738888.html ------------------------------------ ...

  9. Netty 源码解析(三): Netty 的 Future 和 Promise

    今天是猿灯塔“365篇原创计划”第三篇. 接下来的时间灯塔君持续更新Netty系列一共九篇 Netty 源码解析(一): 开始 Netty 源码解析(二): Netty 的 Channel 当前:Ne ...

  10. Netty 源码解析(五): Netty 的线程池分析

    今天是猿灯塔“365篇原创计划”第五篇. 接下来的时间灯塔君持续更新Netty系列一共九篇 Netty 源码解析(一): 开始 Netty 源码解析(二): Netty 的 Channel Netty ...

随机推荐

  1. 更改Linux下的时间

    1.使用tzseletect glibc-common-2.12-1.192.el6.x86_64 : Common binaries and locale data for glibc Repo : ...

  2. 2. C/C++笔试面试经典题目二

    1. C和C++中struct有什么区别? [参考答案] [解析]C中的struct没有保护行为,没有public,private,protected,内部不能有函数,但可以有函数指针. 2. C++ ...

  3. Python实现KNN算法

    Python实现Knn算法 关键词:KNN.K-近邻(KNN)算法.欧氏距离.曼哈顿距离  KNN是通过测量不同特征值之间的距离进行分类.它的的思路是:如果一个样本在特征空间中的k个最相似(即特征空间 ...

  4. 【数据结构】单链表&&静态链表详解和代码实例

    喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 01 单链表(Singly Linked List ) 1.1 什么是单链表? 单链表是一种链式存储的结构.它动态的为节点分配存 ...

  5. Leetcode 8. String to Integer (atoi) atoi函数实现 (字符串)

    Leetcode 8. String to Integer (atoi) atoi函数实现 (字符串) 题目描述 实现atoi函数,将一个字符串转化为数字 测试样例 Input: "42&q ...

  6. [转][Unity3D]引擎崩溃、异常、警告、BUG与提示总结及解决方法

    1.U3D经常莫名奇妙崩溃.   一般是由于空异常造成的,多多检查自己的引用是否空指针.   2.编码切换警告提示.   警告提示:Some are Mac OS X (UNIX) and some ...

  7. nRF51822外设应用[2]:GPIOTE的应用-按键检测

    版权声明:本文为博主原创文章,转载请注明作者和出处.    作者:强光手电[艾克姆科技-无线事业部] 1. nRF51822寄存器类型 nRF51822的寄存器和一般的单片机有所差别,nRF51822 ...

  8. c#Udp分包组包方法

    udp通信协议,相信大家都知道这个.由于是无连接的协议,所有udp的传输效率比tcp高.但是udp协议传输较大的数据文件得分包 最近写了个分包组包的方法,拿来和大家分享,如果有什么不妥的地方,欢迎点评 ...

  9. C++_异常5-异常规范和栈解退

    异常规范 异常规范的理念看似有前途,但实际的使用效果并不好. 忽视异常规范之前,您至少应该知道它是什么样的,如下所示: double harm(double a) throw(bad_thing);  ...

  10. 【算法笔记】B1022 D进制的A+B

    1022 D进制的A+B (20 分) 输入两个非负 10 进制整数 A 和 B (≤2​30​​−1),输出 A+B 的 D (1<D≤10)进制数. 输入格式: 输入在一行中依次给出 3 个 ...