最全最简单的dubbo教程-服务暴露过程《十六》

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jingyangV587/article/details/85713716

服务暴露的总流程

  1. 首先将服务的实现封装成一个Invoker,Invoker中封装了服务的实现类。
  2. 将Invoker封装成Exporter,并缓存起来,缓存里使用Invoker的url作为key,然后注册到注册中心。
  3. 服务端Server启动,监听端口,等待调用。(请求来到时,根据请求信息生成key,到缓存查找Exporter,就找到了Invoker,就可以完成调用。)

服务暴露的详细流程

画图不太会,从网上弄来一张时序图凑合着看吧。
在这里插入图片描述
前三步是解析标签的过程,ServiceBean是标签解析器中的一个,解析标签的过程中会触发ServiceBean这个类,这个类专门负责服务的注册暴露的。从图中可以看出服务暴露详细的有如下几步:
(1)容器创建完之后会触发ServiceBean类中的ContextRefreshedEvent,执行export()方法。
(2)export()方法会调用ServiceConfig中的doExport()方法,这个方法会调用doExportUrls()方法,进而doExportUrlsFor1Protocol()方法。
(3)doExportUrlsFor1Protocol()方法中会利用反射构造invoker,这个invoker封装了服务实现类注册的地址及端口相关信息。同时执行protocol.export()方法。
(4)protocol.export()中的protocol有两个实现类,这个是最关键的,一个是RegistryProtocol一个是DubboProtocol,调用这个方法的时候会首先调用RegistryProtocol类,RegistryProtocol类中的export()方法会调用doLocalExport()方法通知DubboProtocol执行openServer(url)方法进行服务的开启,其实就是开启一个netty服务。同时export()方法会调用ProviderConsumerRegTable.registerProvider()方法进行注册表的缓存以及服务的注册。

源码跟踪详解

前面说过了,标签解析会调用ServiceBean类,这个类实现了ApplicationListener监听的是ContextRefreshedEvent,
这个类在容器启动完之后会调用ApplicationListener中的onApplicationEvent()方法,如图:
在这里插入图片描述

断点进入这个方法,如图:
在这里插入图片描述

这里有一个doExport()方法,在这个方法里面会执行这么一个方法:
在这里插入图片描述

打开这个方法如图:
在这里插入图片描述

protocols里面的protocolConfig包含了注册的协议端口啊之类的信息。注意这里是个list,意思可能有不同的协议不同的端口注册,如果有不同的协议端口的话,会在for循环里面把这些服务分别都暴露一遍。

进入doExportUrlsFor1Protocol继续往下:
前面的都是一些检查校验的主要的在这里,如图:
在这里插入图片描述
图中可以看出wrapperInvoker封装了服务的实现类,服务的定义,暴露的地址端口等信息。然后会执行protocol.export(wrapperInvoker),如图:
在这里插入图片描述
这个接口有多个实现类,包括DubboProtocol与RegistryProtocol类,我们分别在这两个类中export()方法中分别打上断点看看都发生了什么?继续下一步:
在这里插入图片描述
这里有个doLocalExport()方法,其实这个方法就是要进行服务暴露的方法,下面有个ProviderConsumerRegTable.registerProvider()方法,其实就是要进行服务在注册表缓存的,这里先给他打上断点备用。我们先进入doLocalExport()方法,看看都做的啥?
在这里插入图片描述
这里我们发现他会执行一个protocol.export()方法,而这个方法实现了DubboProtocol类,我们继续下一个断点:
在这里插入图片描述
我们进入DubboProtocol类中的export()方法,会发现有个openServer(url),这个URL就是要暴露的服务的地址端口以及接口定义等信息,进入openServer(),会有个createServer(url),继续进入这个方法会有如下:
在这里插入图片描述
我们点进去bind()方法继续下一步:
在这里插入图片描述
在这里插入图片描述
一直往下:
在这里插入图片描述
这里就进入了netty底层了,netty大家至少做过demo吧,开启服务至少会bind一个端口,不知道的可以看看我的另外一个博客用Netty4.x+WebSocket制作简单的聊天系统运行一下demo感受感受。
这里服务的提供者已经开启了,等待服务的提供者连接发送信息。我们放开断点进入之前在RegistryProtocol中的export()方法中的另外一个断点:
在这里插入图片描述
服务暴露完之后会执行这么一个方法ProviderConsumerRegTable.registerProvider(originInvoker, registryUrl, registedProviderUrl);,上面已经说过了是要进行服务缓存的。
其中originInvoker封装了一些接口的实现类,registryUrl封装的注册类型以及端口地址,registedProviderUrl封装了需要暴露的具体提供者的协议啊,暴露的端口地址啊,以及接口定义之类的信息。另外在它下面的一个register()方法中我们先打上断点,这个是要进行服务注册的放。我们先进入ProviderConsumerRegTable.registerProvider()这个方法:
在这里插入图片描述
这里有两个重要的Map一个是服务提供者的,一个是服务消费者的,这里我们注册服务之前我们会把服务提供者相关的信息写到providerInvokers这个map里面,key如图,其实就是接口加版本号。这里我们可以想起来dubbo为什么可以进行多版本控制,其实这里就是分成不同的key值。还有一个重要的概念,记得以前面试的时候有面试官问我,注册中心都宕机了,服务还能继续提供么?这里不得不装下逼了,我们完全可以理直气壮的回答说:能,因为服务的相关的注册信息不仅在注册中心里面而且还会在本地缓存,缓存其实就是一个Map,只要不是所有服务的提供者都宕机了,服务还能继续提供!
装完逼之后我们回到刚才在register()方法中打的断点:
在这里插入图片描述
进入这个方法:
在这里插入图片描述
这里有个重要的类FailbackRegistry,当我们进入这个类会发现如下:
在这里插入图片描述
这里服务提供者会在注册中心注册,从图中可以看出,注册方法有四种。

这里服务的暴露流程基本讲完了,有点啰嗦,功底有限,有问题希望指正,谢谢!

参考博客:
https://blog.csdn.net/jycwl/article/details/51481914
https://www.jianshu.com/p/dcfe426e9cd7

猜你喜欢

转载自blog.csdn.net/jingyangV587/article/details/85713716