从零开始我的rpc第一篇之我认识的rpc
rpc是什么呢.从意思来看,翻译为远程过程调用(Remote Procedure Call),目的就是让远程的函数调用起来就像在本地一样轻松方便.类似我们http请求,接收到远程服务器返回的信息.而rpc定位在函数调用上,底层利用tcp传输,更加高效,从而让我们感觉如同本地调用一般.
为什么我们要使用rpc.rpc很好的帮我们解决了远程跨服务器函数调用的问题,而其偏向于函数层面的特点,也就更加适合于我们这种业务coder们的使用.比如我们的业务涉及到很多,一般会将整个业务拆分为多个服务,然后单独部署.比如我只负责用户这一块的业务,那么当别人需要我的服务的时候,我就需要给别人提供一系列接口,于是我在service层暴漏其他人所需要的接口.这样别人在调用我的服务的时候,就只需要调用我提供的一套接口就行了,而不需要关心接口的实现,业务之间很好的解耦合了.
那好,我们做一个最简单的rpc模型:
[consumer]-->(tcp调用)-->[provider]
这里可以了解到rpc通常分为consumer端和provider端,中间通过tcp通讯传递调用信息.所以如果我们要实现一个简单的rpc,只要照着这个思路就可以了.
那我们实现这三步需要注意下什么呢.
首先,我们日常本地写个函数调用的时候,在一个main函数里面直接写就可以了,比如:
class Demo {
public static void main(String args[]) {
new Demo().methodA();
}
public void methodA() {
}
}
我们在进行函数调用的时候,并没有需要很多复杂的事情要做,但我们能如此方便的调用,都是因为我们在同一台机器上面,实质也就是我们在同一个jvm上进行,我们共享堆空间,我们的方法共享着栈.那当我们拆分为rpc的俩台(或者多台)的时候,我们首先要确保的是不同机器间的通信.也就是我们需要一个运行着的provider和consumer,并保持二者的通信.
看起来只要我们做到这三步好像rpc就已经实现了.那么然后我们想一下这个调用的过程是怎样子的.首先我们写了个provider,比如:
public class IUserService {
public void name(int id);
}
public class UserService implements IUserService {
public void name(int id) {
return "name"+id;
}
}
我们写了个provider,很好,并提供了个接口IUserService.提供?怎么提供了,en,于是我们把这个接口给打个jar包,给了调用方.
然后想想,这只是个类,还需要把她变成个可提供服务的provider,en,因为rpc基于tcp,那我们自然想到用socket绑定端口.
这里略过socket的部分,之后会单独说.
接着,我们看consumer端,我们拿到接口开始调用.问题来了,这只是个接口,没有实现类,我们怎么实例化进行对象调用.我们的实现类可是在provider那里呀.这里就需要我们要考虑去实现的.因为我们缺少实现类,所以我们就需要自己伪造一个,这时候就需要另外一个技术就是代理proxy,而恰好java有原生的proxy实现.
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
这里就是我们实现rpc的关键一步了,我们伪造的实现类有了,而我们通过这个代理类的invoke方法实现我们远程调用的想法.哈哈,当然是socket通信了,我们这里要利用socket怎么做了.首先,我们要知道要调用哪个类的哪个方法,方法的参数是什么,想想如果provider接收这些信息是不是就可以通过某个技术就能调用实际的方法了.en,猜一下应该只有反射reflect可以做到.
现在我们捋一下实现这些事情的思路.首先要理解我们要实现什么功能(远程调用);这些功能是由哪些部分组成(consumer,provider);我们大致了解对每个部分所需要的技术(proxy,socket,reflect).通过理解整个流程的意义,我们写这些就如同我们写业务code一样顺畅.这也是我后面写每个功能都贯彻的整体思路.
到这里好像我们已经掌握了rpc最基本的功能了.但是真正生产级别可不是这么小清新的.我们不妨以阿里的dubbo为例,我们看看她包含了什么(图片源自dubbo官网):
我们可以看到,dubbo包括一个consumer(消费端),provider(生产端),registry(注册中心),monitor(监控中心).其中还包括了cluster(集群)和container(容器),更不必说更细节的东西了.
不过我们从其中的引导线,可以大致看出整个流程.首先consumer和provider都和registry有交互,而monitor是一个单独的部分.provider向注册中心提供service,然后由注册中心通知consumer.consumer通过订阅注册中心,来获取通知.这里的registry很好解决了我们的多服务情况下,我们接口的存放问题,也就是其实单台机器我们是不需要registry的,好像上面我也没提到过注册中心的概念(手动滑稽).
其实dubbo是一个包括很多如集群,负载均衡,降级等一整套的rpc服务治理框架.但我们可以看到,里面最核心的最基本的还是我们上面提到了概念,”实现远程调用“.只要理解了这个基础,我们就可以往里面加注册中心,加集群,加负载均衡.
万丈高楼平地起,当我要实现一个rpc的时候,我没想过rpc到底要有哪些功能.当然,作为一个coder,很难去想的那么深入且完整.所以我们要考虑的就是如何从始至终的保持我们代码的扩展性.其实本没有车,只是我们把所有零部件都造完了,车就有了.
好了,我明确下目的我们要实现个rpc,需要个consumer,provider,registry,可能会有个monitor,其中要包括代理,反射,socket,集群,负载均衡等很多功能.我们要怎么实现这些功能,那就需要我们一步一步的搭积木了.
上一篇: java通过xml-rpc远程过程调用python
下一篇: RPC的实现原理
推荐阅读
-
我眼中的 RPC
-
荐 我的架构梦:(二十)基于Netty手写RPC框架
-
小弟我用jquery的AJAX通过POST过来数据 appliction/json-rpc 接收不到,这是为什么?
-
小弟我用jquery的AJAX通过POST过来数据 appliction/json-rpc 接收不到,这是为什么?
-
从零开始我的rpc第一篇之我认识的rpc
-
从零开始我的rpc第二篇之通信层Consumer端
-
我眼中的 RPC
-
我的职业生涯总结-班门弄斧之我们该怎样从零开始学习.NET_html/css_WEB-ITnose
-
我的职业生涯总结-班门弄斧之我们该怎样从零开始学习.NET_html/css_WEB-ITnose
-
小弟我用jquery的AJAX通过POST过来数据 appliction/json-rpc 接收不到,这是为什么?