一篇文章了解RPC框架原理

1.RPC框架的概念

RPC(Remote Procedure Call)–远程过程调用,通过网络通信调用不同的服务,共同支撑一个软件系统,微服务实现的基石技术。使用RPC可以解耦系统,方便维护,同时增加系统处理请求的能力。

上面是一个简单的软件系统结构,我们拆分出来用户系统和订单系统做为服务存在,让不同的站点去调用。

只需要引入各个服务的接口包,在代码中调用RPC服务就跟调用本地方法一样,我刚接触到这种调用方式的时候颇为惊奇,我明明调用的就是java语言方法啊(已java为例,现在RPC框架一般都支持多语言),怎么就调用了远程的服务了呢??

2.RPC框架的原理解析

最近自己写了一个简单的RPC框架KRPC,本文原理分析结合中代码,均为该框架源码 https://github.com/yangzhenkun/krpc

2.1 流程纵览

如上图所示,我将一个RPC调用流程概括为上图中5个流程,左边3个为客户端流程,右边两个为服务端流程。 下面就各流程进行解析

2.2 客户端调用

服务调用方在调用服务时,一般进行相关初始化,通过配置文件/配置中心 获取服务端地址 用户调用:

// 用户服务接口public interface UserService {    public User genericUser(Integer id,String name,Long phone);

}//调用方//服务初始化KRPC.init("D:\\krpc\\service\\demo\\conf\\client.xml");
UserService service = ProxyFactory.create(UserService.class, "demo","demoService");
User user = service.genericUser(1, "yasin", 1888888888L);

一开始接触RPC调用方法肯定就有疑惑,它不是一个接口吗,直接调用应该没啥效果啊,我也没有引入实现包。

带着这个疑惑,我们就进入下一个知识点,动态代理

2.3动态代理

动态代理这东西意如其名,它代理你帮你做事情。 上面我们不说道直接调用一个接口中的方法,并且没有用该接口的实现类调用,那么方法是怎么生效的呢?

可以看到这个用户服务这个service是由ProxyFactory代理工程创造的,在该ProxyFactory#create()方法中就跟一个代理处理器绑定在一起了

@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    //构造请求request
    Request request = new Request();
    ....

    return RequestHandler.request(serviceName, request,returnClass);
}

这个类实现了InvocationHandler接口(JDK提供的动态代理技术),每次去调用接口方法,最终都交由该handler进行处理。 这个环节一般会获取方法的一些信息,例如方法名,方法参数类型,方法参数值,返回对象类型。

同时这个环节会提供序列化功能,一般的RPC网络传输使用TCP(哪怕使用HTTP)传输,这里也要将这些参数进行封装成我们定义的数据接口进行传输。

2.4网络传输

我们通过将方法参数进行处理后,就要使用发起网络请求,使用tcp传输的就利用socket通信进行传输,这一块我开源项目中使用的同步堵塞的方案进行请求,也可以使用一些非堵塞方案进行请求,效率会更高一些。

2.5服务端数据接受

这一块使用netty,可以快速一个高性能、高可靠的一个服务端。

public class ServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        ByteBuf buf = (ByteBuf)msg;  
        byte[] bytes = new byte[buf.readableBytes()];  
        buf.readBytes(bytes);  

        byte[] responseBytes = RequestHandler.handler(bytes);
        ByteBuf resbuf = ctx.alloc().buffer(responseBytes.length);
        resbuf.writeBytes(responseBytes);
        ctx.writeAndFlush(resbuf);

    }    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

}

上面代码是我项目中使用的服务端代码。关于netty网上学习的资料很多,这里也只是宏观的讲解RPC原理,就不展开。

2.6真实调用

服务端获取客户端请求的数据后, 调用请求中的方法,方法参数值,通过反射调用真实的方法,获取其返回值,将其序列化封装,通过netty进行数据返回,客户端在接受数据并解析,这就完成了一次rpc请求调用的全过程。

method = clazz.getMethod(request.getMethodName(),requestParamTypes);method.setAccessible(true);result = method.invoke(service, requestParmsValues)

上面代码片段为通过反射调用真实方法

2.7 服务端的动态加载

通过2.2到2.6的说明,一次RPC请求过程大致如此,但是一个RPC框架会有很多细节需要处理。

其实在一次请求调用前,服务端肯定要先启动。

服务端作为一个容器,跟我们熟知的tomcat一样,它可以动态的加载任何项目。所以在服务端启动的时候,必须要进行一个动态加载的过程。在KRPC中,我使用了URLClassLoader动态加载一个指定路径的jar包,任何业务服务的实现所依赖的jar包都可以放入该路径中。

3.总结

一个RPC框架大致需要动态代理、序列化、网络请求、网络请求接受(netty实现)、动态加载、反射这些知识点。现在开源及各公司自己造的RPC框架层出不穷,唯有掌握原理是一劳永逸的。掌握原理最好的方法莫不是阅读源码,自己动手写是最快的。

https://github.com/yangzhenkun/krpc

这是我最近开始写的一个RPC框架,麻雀虽小五脏俱全,虽然这个框架我还在开发中(还有一些功能没有完成),欢迎一起讨论,star,这个框架中有很多地方可以改进的点。

文章转自:https://blog.csdn.net/u013592964/article/details/80441205

原文发布于微信公众号 - JAVA高级架构(gaojijiagou)

原文发表时间:2018-05-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Crossin的编程教室

Python 实战(3):更多的页面

现在我们网站已经有了一个简单的页面、一段简单的请求处理代码和一个简单的数据库。上次最后我剧透了下,之后将会通过豆瓣电影的 API 获取更多的电影数据。不过在此之...

28850
来自专栏Golang语言社区

深入Go语言网络库的基础实现

Go语言的出现,让我见到了一门语言把网络编程这件事情给做“正确”了,当然,除了Go语言以外,还有很多语言也把这件事情做”正确”了。我一直坚持着这样的理念——要做...

29770
来自专栏码洞

求不更学不动之Redis5.0新特性Stream尝鲜

Redis5.0最近被作者突然放出来了,增加了很多新的特色功能。而Redis5.0最大的新特性就是多出了一个数据结构Stream,它是一个新的强大的支持多播的可...

18860
来自专栏Java进阶架构师

手把手带你实现JDK动态代理

业务接口Interface、业务实现类target、业务处理类Handler、JVM在内存中生成的动态代理类$Proxy0

8420
来自专栏玩转JavaEE

ElementUI中tree控件踩坑记

vhr部门管理模块更新啦!为了让小伙伴们快速理解部门管理模块实现思路,我想通过3篇短文来给大家介绍下大致的实现思路和核心代码。 项目地址:https://git...

51860
来自专栏FreeBuf

一个漏洞为何能影响数千万服务器以及66%安卓手机?

安全研究团队Perception Point发现Linux系统内核中存在一个高危级别的本地权限提升0day漏洞,编号为CVE-2016-0728。目前有超过66...

23050
来自专栏Java帮帮-微信公众号-技术文章全总结

同步与异步/阻塞与非阻塞/回调【面试+工作】

  打个比方,比如我们去购物,如果你去商场实体店买一台空调,当你到了商场看中了一款空调,你就想售货员下单。售货员去仓库帮你调配物品。这天你热的实在不行了。就催着...

13320
来自专栏FreeBuf

别用Chrome浏览这篇文章,会崩溃!

早前就有8个字符让Skype崩溃的例子,今天我们提到的是16个字符让Chrome崩溃,你只需要点击这16个字符,甚至鼠标只是在这16个字节组成的链接周围移动都可...

20760
来自专栏java一日一条

40+个对初学者非常有用的PHP技巧(二)

考虑使用ob_gzhandler?不,别这样做。它没有任何意义。PHP应该是来写应用程序的。不要担心PHP中有关如何优化在服务器和浏览器之间传输的数据。

10510
来自专栏Java3y

COW奶牛!Copy On Write机制了解一下

触及到知识的盲区了,于是就去搜了一下copy-on-write写时复制这个技术究竟是怎么样的。发现涉及的东西蛮多的,也挺难读懂的。于是就写下这篇笔记来记录一下我...

25230

扫码关注云+社区

领取腾讯云代金券