RPC 框架
RPC
谁能用通俗的语言解释一下什么是 RPC 框架? - 远程过程调用协议RPC(Remote Procedure Call Protocol)
RPC就是要像调用本地的函数一样去调远程函数。
推荐:https://www.zhihu.com/question/25536695
RPC框架解释
首先了解什么叫RPC,为什么要RPC,RPC是指远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送-一个有进程参数的调用信息到服务进程,然后等待应答信息。
比如两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。比如说,一个方法可能是这样定义的:
Employee getEmployeeByName(String fullName)那么:
-
首先,要解决通讯的问题,主要是通过在客户端和服务器之间建立TCP连接,远程过程调用的所有交换的数据都在这个连接里传输。连接可以是按需连接,调用结束后就断掉,也可以是长连接,多个远程过程调用共享同一个连接。
-
第二,要解决寻址的问题,也就是说,A服务器上的应用怎么告诉底层的RPC框架,如何连接到B服务器(如主机或IP地址)以及特定的端口,方法的名称名称是什么,这样才能完成调用。比如基于Web服务协议栈的RPC,就要提供一个endpoint
URI,或者是从UDDI服务上查找。如果是RMI调用的话,还需要一个RMI Registry来注册服务的地址。 -
第三,当A服务器上的应用发起远程过程调用时,方法的参数需要通过底层的网络协议如TCP传递到B服务器,由于网络协议是基于二进制的,内存中的参数的值要序列化成二进制的形式,也就是序列化(Serialize)或编组(marshal),通过寻址和传输将序列化的二进制发送给B服务器。
-
第四,B服务器收到请求后,需要对参数进行反序列化(序列化的逆操作),恢复为内存中的表达方式,然后找到对应的方法(寻址的一部分)进行本地调用,然后得到返回值。
-
第五,返回值还要发送回服务器A上的应用,也要经过序列化的方式发送,服务器A接到后,再反序列化,恢复为内存中的表达方式,交给A服务器上的应用
为什么RPC呢?就是无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如比如不同的系统间的通讯,甚至不同的组织间的通讯。由于计算能力需要横向扩展,需要在多台机器组成的集群上部署应用。
要知道实现RPC很麻烦呀,什么多线程、什么Socket、什么I/O,都是让咱们普通程序员很头疼的事情。于是就有牛人开发出RPC框架(比如,CORBA、RMI、Web Services、RESTful Web Services等等)。简单点讲,RPC框架就是可以让程序员来调用远程进程上的代码一套工具。有了RPC框架,咱程序员就轻松很多了,终于可以逃离多线程、Socket、I/O的苦海了。
RPC的协议有很多,比如最早的CORBA,Java RMI,Web Service的RPC风格,Hessian,Thrift,甚至Rest API。
关于Netty
而Netty框架不局限于RPC,更多的是作为一种网络协议的实现框架,比如HTTP,由于RPC需要高效的网络通信,就可能选择以Netty作为基础。除了网络通信,RPC还需要有比较高效的序列化框架,以及一种寻址方式。如果是带会话(状态)的RPC调用,还需要有会话和状态保持的功能。大体上来说,Netty就是提供一种事件驱动的,责任链式(也可以说是流水线)的网络协议实现方式。网络协议包含很多层次,很多部分组成,如传输层协议,编码解码,压缩解压,身份认证,加密解密,请求的处理逻辑,怎么能够更好的复用,扩展,业界通用的方法就是责任链,一个请求应答网络交互通常包含两条链,一条链(Upstream)是从传输层,经过一系列步骤,如身份认证,解密,日志,流控,最后到达业务层,一条链(DownStream)是业务层返回后,又经过一系列步骤,如加密等,又回到传输层。
这样每一层都有一个处理接口,都可以进行不同的操作,比如身份认证,加解密,日志,流控,将
不同的处理实现像拼积木那样插接起来就可以实现一个网络协议了(快速开发) 。每层都有自己
的实现,上层不需要关注面向网络的操作 (可维护) 。Netty已经提供了很多实现。
当然Netty还有许多好处,比如对非阻塞I0 (NIO) 的支持,比如在链上传递时最大程度的减少
buffer的copy (高性能)。
netty跟RPC有什么关系
RPC要做到用户无感知的调用远程服务必定要经过网络传输,而netty正好是是Java编写的快速开发高性能高可靠性的网络编程框架。
目前使用netty作为传输层的RPC框架很多,国内知名的有dubbo,motan等。
下面以新浪开源的motan为例,说明netty在RPC的位置:
下图中transport即使使用netty实现的。
总结来说,netty就是解决RPC网络传输的。
分布式RPC需要解决哪些问题呢?
- protocol:传输协议
- proxy:client代理,服务引用方调用方法通过代理发送远程消息
- codec:协议编解码压缩等
- transport:协议传输
- registry:注册中心,服务注册服务发现
- cluster:负载均衡,服务容错策略
- 其他:服务降级,服务隔离,服务治理
如何实现一个分布式的RPC框架呢?
现在互联网已经很少单点服务了,一个好的rpc框架能帮我们省掉很多工作,那么如何撸一个自己喜欢的RPC框架呢?
现在写rpc框架已经不难了,我们可以有很多参考,很多成熟的第三方开源项目可以依赖,可以说是站在巨人的肩膀上。
第一步,选择传输协议:
高性能的rpc和良好的编码协议是分不开的。好的协议不仅耗用流量小,而且序列化和反序列化更快。
现在比较流行的协议有thrift,protobuf,json,restful等。其中thrfit和protobuf性能都比较优异,而且占用空间小,最重要的是跨语言,具有语言平台无关性。但,美中不足的是他们都需要预先根据协议文件预先生成好代码。开发极不流畅。
我们也可以自定义协议,像dubbo和motan一样,定制自己的私有协议,
比如motan协议的header部分如下:
body部分采用hession或者fastjson序列化,
如果不考虑跨语言,这种算是比较完美的解决方案。
定义协议过程中的一些重要且容易忽略的问题:
- 协议版本号
- 消息id
- 协议扩展字段
第二步,协议传输层
一个高性能RPC框架最重要的四个点就是:传输协议,框架线程模型,IO模型,零拷贝。
java程序如果能做好这四点,那么性能应该不会比c++程序差多少。
而作为java开发者,netty正好解决了后三个点,所以使用netty作为RPC框架的传输层会事半功倍。
第三部,注册中心的选择
现在有很多提供服务注册发现的服务,实现成本比较低就是zookeeper,可以很容易的实现服务注册和服务发现的功能。
解决了这三部,后面的就得脚踏实地码代码了,当然后续会有很多细节,不过都不是问题,现在有好多成熟的开源框架可以参考。
当然也可以参考我最近实现的分布式RPC框架,也欢迎提issue(后续会持续优化)。
自己撸一个RPC还是很不错的,如果有兴趣建议自己撸一遍玩玩。
下面是广告时间>>>>>>>>>
dempeZheng/forestRPC 基于netty, spring,轻量的高性能分布式RPC服务框架
Overview
基于netty, spring,轻量的高性能分布式RPC服务框架。简单,易用,高效。
Features
- 服务端支持多种序列化方式:fastjson,hession,kryo
- 服务端支持多种压缩方式:gzip,snappy
- 服务端可根据group进行线程隔离,支持基于spring对不同的group配置不同的业务线程池
- 支持注解配置,也支持spring xml配置
- 支持服务发现服务注册
- client端支持多种负载均衡策略和容灾策略
- client内置连接池
- 基于netty 4.x版本实现,高性能(win 8cpu单机8w+)
TODO
- 服务降级功能
- http服务支持
- 跨语言协议支持
- 服务治理管理后台
郑大侠的回答 - 知乎
https://www.zhihu.com/question/25536695/answer/134976748
RPC流程
RPC:远程调用。通过RPC框架,使得我们可以像调用本地方法一样地调用远程机器上的方法:
1、本地调用某个函数方法
2、本地机器的RPC框架把这个调用信息封装起来(调用的函数、入参等),序列化(json、xml等)后,通过网络传输发送给远程服务器
3、远程服务器收到调用请求后,远程机器的RPC框架反序列化获得调用信息,并根据调用信息定位到实际要执行的方法,执行完这个方法后,序列化执行结果,通过网络传输把执行结果发送回本地机器
4、本地机器的RPC框架反序列化出执行结果,函数return这个结果
服务调用端(本地机器):
服务提供端(远程机器):
Java Netty 是在TCP(Socket)层对nio进行封装的框架,在RPC框架中可用于解决网络传输问题。
现在流行的微服务框架(dubbo、spring cloud等),实际上就是各种各样的RPC框架