欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

从零开始我的rpc第一篇之我认识的rpc

程序员文章站 2022-06-01 21:32:58
...

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官网):
从零开始我的rpc第一篇之我认识的rpc
我们可以看到,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,集群,负载均衡等很多功能.我们要怎么实现这些功能,那就需要我们一步一步的搭积木了.

相关标签: rpc