![](https://img.haomeiwen.com/i1041678/941748cba87027f9.png)
前言
本篇讲的是dubbo中比较重要的远程暴露
,鉴于上一篇dubbo源码解析-本地暴露采用一图胜千言的写法好像读者并不太容易理解,加上之前写的别怕看源码,一张图搞定Mybatis的Mapper原理中的读者评论中看出,这种方式可能有点粗暴.这个后面有时间会补上一些更细致的文字说明
自从每周一更以来,也有不少朋友问到我怎么看源码
这个问题.鉴于高中老师告诉我,作文怕走题的话,就要时刻点题.这种点题的思想也一直延续到现在,所以我的源码解析系列,也几乎都把自己分析的思路暴露出来,其实也是时刻在回答这个怎么看源码
的问题.
昨天下午一个好朋友也打电话给我,说他去面试(广州)问到了从看源码中你学到了什么?
这个问题.其实能学到的东西就太多了.比如你看任何一个框架的源码,那么首先要看一下设计模式
吧,任何一个成熟的框架少不了工厂模式.再具体一点,看dubbo源码
,你就要顺便学一下zookeeper
,netty
,spring事件机制
的一些简单知识.像SPI
,javassist
这些知识你工作了几年可能还没用过吧.同时我们根据这些再深入思考一下,比如dubbo中拼接生成动态编译类的做法,我们可不可以用其他方式来实现呢?比如通过freemarker
这样的模板引擎.既然能生成动态编译类,那像CRUD这种比较固定的代码,我们是不是又可以用这个模板引擎做一个代码生成器
呢?
言归正传,我们回到主题.鉴于前面提到的点题思想,就那以本篇为例,时刻提一下从源码中你学到了什么
插播面试题
- 服务暴露中远程暴露的总体过程,画图和文字方式说明
预热概念
首先上一张dubbo文章中非常经典的一张图
![](https://img.haomeiwen.com/i1041678/a08cc70f2d564140.png)
相信大家初学dubbo的时候都看过这张图,但是可能当时没理解这个图究竟想说的是什么.图中圈出来的部分就是今天要讲的远程暴露
,当然我还会做一些补充.
为什么这次我不直接自己画图,而是引用官方文档的图?原因很简单,因为假如我直接把图画出来,就是相当把这些概念填鸭式的告诉你,这样你无法看到我的思考过程,也就是说,我并没有告诉大家,这些东西我是怎么知道的,然而这一点,才是源码解析类文章,最应该表达的思想.所以我每篇文章都先从文档入手,以dubug代码的方式验证,这就是我的思考过程,也是我看源码的过程(粗暴式点题怎么看源码).当然后面视情况也会补上一些个人自己花的图加以总结.
另外注意的是,图中的箭头方向是从Consumer
到Provider
的过程,所以这个暴露的过程,是我红框出来的反方向
直入主题
由于前两篇dubbo源码解析-服务暴露原理和dubbo源码解析-本地暴露已经多次讲述了getInvoker
的过程,远程暴露也大同小异,所以不再细述.直接从protocol.export(invoker)
开始,另外每个截图我都会尽量把类名和方法名截图出来,方便读者一起debug,另外这些动态编译类(黄色圈出来的)调试方式请参考服务暴露原理
这篇
![](https://img.haomeiwen.com/i1041678/fa371a6d5d49e64c.png)
由经典的交互图知道,下一个关键词是Filter
,由于这个也和前面讲得大同小异,所以就将过程简单浏览回顾一下
![](https://img.haomeiwen.com/i1041678/e1d627cdf629bf3e.png)
![](https://img.haomeiwen.com/i1041678/ab547e697da279cc.png)
![](https://img.haomeiwen.com/i1041678/93a70d477a5ffac3.png)
![](https://img.haomeiwen.com/i1041678/289370e1434e24a0.png)
![](https://img.haomeiwen.com/i1041678/9a43509f9b5392f4.png)
![](https://img.haomeiwen.com/i1041678/07cedeb55c4fbaa2.png)
![](https://img.haomeiwen.com/i1041678/b5db95749c4cc319.png)
![](https://img.haomeiwen.com/i1041678/60b92acf2d7dba81.png)
![](https://img.haomeiwen.com/i1041678/c7566570a6ad4422.png)
下面我们似乎又看到了一位熟悉的老朋友,在本地暴露
中我们也看过这行代码,为何本地暴露
和远程暴露
中都有他的身影?欢迎简书关注肥朝,在服务引用
那一节我们再揭秘
![](https://img.haomeiwen.com/i1041678/ed436bfcdcbd60c1.png)
同时我们已经到了第三个关键词Procotol
,老规矩,我们来看看他的继承体系图(粗暴式点题,怎么看源码)
![](https://img.haomeiwen.com/i1041678/a326498437fe58b7.png)
那这种继承体系有什么好处呢?要想说明一个代码好,那就必须拿个比较一般代码来对比了.由于篇幅有限,推荐看大话设计模式
的第一章,该章用一个计算器的例子,将一个比较一般的代码一步一步演进成类似结构(粗暴式点题,从看源码中学到了什么).
按照经典图的路线,我们下一个关键词应该就是Server
了,从方法名openServer(url)
也可以看出来确实是这样.当然我在预热概念
中也提到,我会做一些补充,那么我要在这个Procotol
和Transporter
插播一个关键词,那就是Exchanger
![](https://img.haomeiwen.com/i1041678/f09e1fd26535f696.png)
![](https://img.haomeiwen.com/i1041678/12c620320d2ef672.png)
![](https://img.haomeiwen.com/i1041678/b32aed7cad70227b.png)
从单词意思我们知道,这个是交换
的意思,按照计算机术语,这个称之为交换层
更贴切.那么问题来了,他交换什么东西?那我们来看一下他的方法图(粗暴式点题,怎么看源码)
![](https://img.haomeiwen.com/i1041678/f0bc1bbfd15b74a8.png)
我们捕捉到了几个关键词,Client
,Server
,其实这个交换层,就是做封装请求与响应
之间的交互层.那么为什么需要这么个交互层呢?这么设计有什么好处呢?好,那我们打开阿里巴巴Java开发手册
![](https://img.haomeiwen.com/i1041678/6fee32e9194f186c.png)
我来举个例子,java web
中传统的请求响应方式都是controller->service->dao
,然后dao->service->controller
,从手册我们知道,从dao
传出来的是DO
,但是controller
需要的是VO
,那么我们是不是需要一个中间的交互层来做这些转换?这个例子虽然不足以描述这种设计的好,但是比较可能比较好理解一些.(粗暴式点题,看源码学到了什么)
那我们继续往下走
![](https://img.haomeiwen.com/i1041678/f593959e8da0aedc.png)
![](https://img.haomeiwen.com/i1041678/65e3e9e697fe94cf.png)
![](https://img.haomeiwen.com/i1041678/a25682146c018f7a.png)
下面就要注意了,我们要来到下一个关键词Transporter
,这个从字面理解为传输层
,那这个究竟是什么传输层?我们来看一下继承体系图(粗暴式点题,怎么看源码)
![](https://img.haomeiwen.com/i1041678/be841049c17f05b5.png)
从这里就可以看出,这个是网络传输层
,其中Grizzly
和Mina
和Netty
都是非常有名的NIO框架,想了解他们可以查一下相关资料(粗暴式点题,看源码学到了什么)
![](https://img.haomeiwen.com/i1041678/64b5cfbf0cd64b9e.png)
![](https://img.haomeiwen.com/i1041678/e1bf1d58378fee1a.png)
![](https://img.haomeiwen.com/i1041678/cff4ada9a6820358.png)
![](https://img.haomeiwen.com/i1041678/843318a72e2e87e1.png)
继续往下走,看到这里有个构造方法,那么就要敲黑板画一下重点了.看源码凡是遇到构造方法的,都要特别注意,因为我们知道调用构造方法前,会先调用父类的构造方法,因此,这个继承体系图是要看一下的(粗暴式点题,怎么看源码)
![](https://img.haomeiwen.com/i1041678/89e4a7094be91115.png)
![](https://img.haomeiwen.com/i1041678/b491a2c6876d702d.png)
因此我们将断点打到他的父类上,可以看出,这做的主要是一些根据配置文件设置一些超时时间之类的
![](https://img.haomeiwen.com/i1041678/c8fb7cad37132182.png)
![](https://img.haomeiwen.com/i1041678/a89790adcf01340e.png)
![](https://img.haomeiwen.com/i1041678/9fb3cb36ab3a859c.png)
高潮还没完,我们注意到,在AbstractServer
类中有一个doOpen()
方法.这个doOpen()
方法方法是一个抽象方法,这种做法称之为钩子方法
.也叫模板方法
,熟悉设计模式的话,会对这种方式并不模式,其实在Servlet
的init()
方法也是这种做法,可以看看Servlet
的源码(粗暴式点题,看源码学到了什么)
那么我们就到了doOpen
方法,这里如果大家写过一些简单的netty例子看到这段代码就会很熟悉了
![](https://img.haomeiwen.com/i1041678/aa38e884afce00d4.png)
另外提一下这个9
并不是固定的,这个和我们的机器是有关的,不熟悉的参数我们可以用以下的方式查一下文档(粗暴式点题,怎么看源码)
![](https://img.haomeiwen.com/i1041678/201f3af44bf6445b.png)
![](https://img.haomeiwen.com/i1041678/89c3dc8cd1f04193.png)
那么继续走,这里为什么会进入这个构造方法呢?注意我们在提Transporter
关键词之前是有new
一个HeaderExchangeServer
对象的.在这个构造方法中,通过startHeatbeatTimer
设置了netty的心跳,这些netty的细节我们在后面的netty专题再细说
![](https://img.haomeiwen.com/i1041678/b3127adeee2b5879.png)
正如官方文档所说Dubbo 处理服务暴露的关键就在 Invoker 转换到 Exporter 的过程
,看到这个exporter
,也预告本篇走到了尾声
![](https://img.haomeiwen.com/i1041678/b41c8320dafde447.png)
写在末尾
本篇中比较粗暴的多次进行怎么看源码
和看源码学到了什么
的点题,让我仿佛回到了高中写作业的时光.当然这种方式也只是肥朝个人的拙见,并不是看源码的最佳实践.有好的想法也欢迎和我交流,我们下周见.鉴于本人才疏学浅,不对的地方还望斧正,也欢迎点赞或者关注我的简书,名称为肥朝
网友评论