Dubbo源码解析 —— 服务暴露原理
前言
之前讲完了dubbo集群容错系列,现在开始讲比较重要的环节,也就是dubbo面试中比较喜欢问的两个点: 服务发布
和 服务引用
.
插播面试题
- 服务发布过程中做了哪些事
- dubbo都有哪些协议,他们之间有什么特点,缺省值是什么
- 什么是本地暴露和远程暴露,他们的区别
直入主题
从启动日志说起
大家都知道, dubbo
是阿里巴巴开源的一个项目,前阵子阿里不仅发布的代码规范手册,还发布了相应的插件,从这点我们就知道,阿里是很注重这个代码规范的,从 dubbo
项目我们也发现了,他有完善的测试体系.说了这么说,那和我们今天要讲的 dubbo的服务发布
有什么关系呢?当然有,一个规范的项目,必然是有健全的日志系统.做过其他开发比如iOS开发的都知道,这个控制台输出在生产环境是不能随便输出的,太多日志有时候和没有日志是一样的.所以我们来看看这个服务启动过程中,日志究竟输出了什么.
这里我用不同颜色的框将关键的地方画了出来,一共有6种颜色,我一次从上到下说一下这发布过程的一些动作
- 暴露本地服务
- 暴露远程服务
- 启动netty
- 连接zookeeper
- 到zookeeper注册
- 监听zookeeper
从文档入手,了解全局
经常有人问到,看源码要怎么看.要了解这个服务发布,文档就是一个很好的切入口,如下
再献上文档提供的一个时序图
当然这些都是给已经对源码有一定熟悉的人看的,而我的源码解析类文档,是给对源码不熟悉的人看的.
其实我的每周一更dubbo源码系列文章,我的初衷有以下两个,一个就是做到系统分享,比如dubbo系列文章,我会从不少于 内核
, 服务发布
, 服务引用
, 编解码
这四个模块去剖析,后面如果有时间,会临摹一个简易的dubbo框架.另一个初衷就是把自己思考的过程和大家分享,在这个分享过程中,其实就是回答了"怎么看源码"这个问题
那么准备好五菱宏光,向秋名山出发
出发秋名山
我早年做Android开发的时候,就发现身边的人都是死在了一个点上,那就是 配置环境
.对于看源码,很多人最常问的一句话就是,怎么入手,也就是切入点.那么我们还是以开头的日志为例,来找一个这个切入点
仔细看输出日志,就会发现在暴露本地服务之前,有一句很重要的日志,就是
The service ready on spring started. service: com.alibaba.dubbo.demo.DemoService, dubbo version: <span class="hljs-number">2.0</span>.0, current host: <span class="hljs-number">127.0</span>.0.1
我们利用编译器的搜索文本功能,定位到了 ServiceBean
这个类,这个类是干嘛的?好,我假设我也不知道,既然不知道,那我们来看一下他的继承体系图
从这个图我们看到了许多和spring有关的东西,还发现了一个重要的接口,那就是 ApplicationListener
.要能敏锐的发现这个关键的接口,首先还是要对spring有一定了解,这个就是spring的事件机制(event).什么是事件机制呢?就比如监听 spring容器初始化完成
.那我们就定位到这行日志的位置,往下debug
下面要开始敲黑板划重点了.
从方法名我们很直观知道目的,但是这里同事不止一次问过我,这个 dubbo.properties
文件是怎么时候加载的,好像我根本没有设置,另外这个 dubbo.properties
文件的名字能不能改?面对这种问题,我从来都是不会直接把答案告诉他,而是告诉他,我是怎么得到这个答案的,如下图
同理,对于 log4j.xml
这个文件,好像我从来没有写代码加载过,为什么他会加载呢,其实也是同理的
接下来继续往下走,下面这里就是我们的第二道面试题
这里为什么会进行遍历呢,因为dubbo是支持多协议的,看文档原话
dubbo支持多种协议,默认使用的是 dubbo
协议,具体介绍官方文档写得很清楚,传送地址:相关协议介绍
马不停蹄,下面就到了第三个面试题,也是服务发布的重点, 本地暴露
和 远程暴露
为什么会有 本地暴露
和 远程暴露
呢?不从场景考虑讨论技术的没有意义是.在dubbo中我们一个服务可能既是 Provider
,又是 Consumer
,因此就存在他自己调用自己服务的情况,如果再通过网络去访问,那自然是舍近求远,因此他是有 本地暴露
服务的这个设计.从这里我们就知道这个两者的区别
- 本地暴露是暴露在JVM中,不需要网络通信.
- 远程暴露是将ip,端口等信息暴露给远程客户端,调用时需要网络通信.
本篇着重讲解 服务发布
的整体过程,细节和总结后面会陆续展开.我们忘记下.其实注意一下我这些截图就能发现,我截的时候会特意把类名和方法名都截出来,方便大家能迅速定位.
从上图可知,这里用到了 Adaptive
(这个东西非常关键,后面会专门一篇讲解).点进 ProxyFactory
查看源码
@Adaptive
注解打在类上和方法上,他们是有区别的(面试也喜欢问这种区别类的问题,这个留在 Adaptive
专题说,记得关注肥朝每周一篇源码解析 _ ),他打在方法上,就会生成动态编译的Adaptive类,下面就介绍一下怎么看这个动态编译类的源码
首先要将这个log4j的level调整为 DEBUG
为什么需要调整成 DEBUG
,更重要的是把如何知道的,告诉大家,比如如下图,当然这个时候可能会朋友说,我也不知道这个类也还是没办法找到这行代码.其实这个也是在后面专门的一篇 Adaptive
中会说,到时候我会提供另一种实现思路,我们一起思考对比优劣.
打开 DEBUG
后,我们重新启动,就会看到日志有如下输出,这段就是相关代码,我们根据包名新建文件,如下
我们在 getInvoker
方法上打上断点,重启一下.
由上图知道,本地暴露的url是以 injvm
开头的,下面来看下远程暴露,其实这个也是回答 本地暴露
和 远程暴露
区别的一个回答点.面试回答要的并不是一个满分的答案,而是从一些细节中,看出一个人,是否真的研究过源码.
还是回到开头那句话, dubbo
命名是很规范的,从 Wrapper
这个命名,其实可以和Spring的 BeanWrapper
,以及装饰者设计模式联系起来.同时可以看看文档中的
编码约定
写在最后
上面讲到了 getInvoker
方法,也就是拿到了 Invoker
,如果注意到本篇开头的文档说明中的那句 Dubbo处理服务暴露的关键就在Invoker转换到Exporter的过程
,就知道,其实这个 服务暴露
还有很多细节是未完待续的,但是由于本篇已有一定篇幅,所以只能下周再见.
如果对你有所帮助,希望点赞,关注支持.鉴于本人才疏学浅,不对的地方还望斧正,也欢迎关注我的简书,名称为 肥朝
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【Linux系列-2】iostat命令详解
- 【Mybatis-1】MyBatis注解版详解
- 【MyBatis-2】MyBatis之xml 配置版
- 【MyBatis-3】MyBatis xml映射文件详解
- 【剑指Offer】II-数组中数字出现的次数 II
- 【MyBatis-4】MyBatis之动态SQL
- 【MyBatis-4】MyBatis批量insert、update、delete数据
- 【redis6.0.6】深入源码,一探究竟 -- redis服务器开机自启动
- 不是你记忆中的单例模式,但适用的程度,更胜一筹
- 安卓模拟器修改hosts文件
- 为容器化的 Postgres 数据库启用 ssl 连接
- 【SpringBoot web-1】web项目数据校验
- 【SpringBoot web-2】web项目参数传递
- 筛法求素数
- redis学习(十三)