前言
在我不了解一项技术时,我特别痛恨技术文档里那些故弄玄虚的词,因为他会打击我学习的积极性 。在我掌握了一项技术后,我发现他们都是纸老虎 。在我深入理解一项技术后,我发现这些词并不是在故弄玄虚,因为没有比它更简洁的表达。这个系列会用最白话的方式来阐述dubbo里的方方面面
1. 什么是服务暴露
先来看一段 dubbo provider 的配置
<bean id=“xxxService” class=“com.xxx.XxxServiceImpl” /> //spring 中一个普通的java bean
<dubbo:service interface=“com.xxx.XxxService” ref=“xxxService” /> //将spring中普通的java bean 转化为dubbo provider
这是一段很常见spring dubbo 配置(基于注解、API编程也是等价的),在很多分析dubbo原理的文章里,在分析这段配置背后的逻辑时,经常会蹦出来一个词 —— 服务暴露
2. 用大白话解释下 “服务暴露”
先允许我把你们当做刚入门的小白,我们先从源头说起 ……
本地方法调用 vs 远程方法调用(RPC)
public class Test {
@Autowired
UserService userService ;
public void addUser(){
User user = new User();
userService.addUser(user);
}
}
这是一段很简单的代码吧,userService
的 addUser
方法负责增加用户
那么请问 userService.addUser(user);
这行代码中的 userService
对象是在哪儿呢? 有可能就是在当前JVM 堆里,也有可能他只是个傀儡,真正的执行是在远程,比如在美国的一台电脑上
如果userService就是在当前JVM里,那么这行代码就是最普通的调用——本地方法调用
如果userService真正的逻辑执行是在远程,本地的只是个傀儡,那么这行代码就是远程方法调用
dubbo 里的方法调用方式就是这一类RPC远程调用,比如: userService.addUser(user);
如果这里的 userService 是dubbo 的consumer ,那么本质上userService就是个傀儡,真正 addUser(user)
这个动作是要在远程执行的
本地的dubbo consumer 执行 userService.addUser(user);
的时候,首先会收集所需的各种信息(userService 这个class, addUser 方法,user对象信息等),在把这些收集到的信息序列化成 byte 字节流,userService 这个傀儡会负责把字节流通过网络传输到远程,远程收到这些信息后,会反序列化还原这些信息。于是乎远程那个真正的userService就知道要去调哪个类的哪个方法,入参是什么等,远程就真正执行 addUser(user)
这个逻辑
问题的出现
看完上面一段叙述,突然发现一个问题: 本地的userService 这个傀儡怎么知道这个所谓的 远程
在哪里啊?最起码他要知道远程的 ip地址和端口号吧,不然怎么发起网络连接呢,怎么传输收集到的字节流呢?
一个最简单的思路 ,首先远程那个真正的userService需要把自己暴露给外界,他需要在远程监听一个ip、端口号,然后把这个ip、端口号放到一个公共的地方(所有人都能访问),这样本地的傀儡在发起网络连接的时候,可以先到这个公共的地方查一下,根据查到的ip、端口发起网络连接
3. 暴露的本质
综上,得出暴露的本质就是: dubbo provider端监听一个ip、端口号,并注册到公共地方(zk)
知道这个本质了,看源码还不简单么