共计 2012 个字符,预计需要花费 6 分钟才能阅读完成。
RPC 是近程过程调用(Remote Procedure Call)的缩写模式, 是在多任务操作系统或联网的计算机之间运行的程序和过程所用的通信技术。
开局
撸码的人都应该晓得,古代编程中最罕用的零碎之间通信形式是:http 调用和 rpc 调用。对于同一个网络或者说是互通的网络环境中,rpc 调用形式是零碎间通信交互最罕用的形式,比基于 http 协定的通信形式性能高出数倍甚至数个量级。我司的平台 rpc 通信,每秒在几万甚至更高,每次调用的通信工夫在肯定水平上简直能够忽略不计,再加上咱们首席架构师深厚的零碎设计功力,采纳过程内缓存等等优化措施,一次 rpc 调用的整体均匀工夫也在一毫秒之下。这是 http 协定无奈达到的速度,如果你在浏览器的 F12 的窗口察看过,一个 http 协定调用如果整体破费的工夫在 5 毫秒甚至 10 毫秒,那么其实就能够认为这个 http 申请响应工夫是很短的了。
所以绝大部分公司外部的零碎之间通信都会采纳 rpc 调用这种形式。这里不要抬杠,如果你的公司外部零碎通信采纳的是基于 http 协定的,那阐明你们的零碎很有可能没有性能的要求。
RPC 调用尽管简化了撸码的难度,然而想要实现一套 rpc 框架,何止容易,一套优良的 rpc 框架,更是难如登天。
连贯服务
少数 rpc 框架的服务端以 service 的形式来运行,为了防止和其余过程产生监听端口的抵触,个别会随机抉择一个端口来进行监听。尽管这看上去很好,然而却给 client 端带来了麻烦,如果服务端监听固定端口,client 连贯服务端的时候,起码能够在代码中固定写死服务端的 IP 和端口。然而当初服务端监听的端口是随机的,而且更可怕的是服务器有可能会更换或者切换 IP,那 client 怎么能力正确的去和服务端建设连贯呢?
服务端之所以会采纳这种随机形式来监听端口,其中很大一个起因是为了当前扩容。client 如何正确的去连贯服务器则采纳了一个集中式的计划,服务端引入了一个服务注册核心的概念,有的零碎可能会以别的名称来体现,然而作用是相似的。这个注册核心存储着所有的服务端信息,其中包含每个服务端的 IP 和端口,有的甚至还有版本信息,每个服务端过程启动的时候,都是采纳被动连贯注册核心,被动注册的形式。client 端在发动连贯服务的时候,首先去注册核心查找曾经注册的服务端信息,而后进行连贯。这样 rpc 调用在某种程度上在连贯步骤就实现了“自动化”。
调用办法
当 client 和服务端建设 tcp 连贯之后(有的 rpc 框架会采纳 udp 协定),下一个问题就是 client 和服务端怎么相认的问题了。举个栗子:客户端想要实现一个获取用户姓名的办法,办法名怎么定义能力让服务端正确辨认进去呢?是传一个字符串“GetName”, 还是传一个整数 1 来代表呢?服务端的返回后果,如果产生异样改如何返回呢?
当咱们在本地调用一个函数,语法,语义,以及语法语义的剖析,编译器曾经帮咱们做好了这些,然而 rpc 是近程过程调用,尽管外表上和本地相似,然而曾经呈现了跨网络的状况,语法语义等等这些剖析须要 client 和服务端协商一致。
其实古代简直大部分 rpc 通信都遵循一个规范:
当 client 发动一个近程调用的时候,它首先会先调用本地的 Stub,它负责将调用的接口,函数以及参数依照约定好的协定格局进行编码,而后通过本地的 Runtime 进行传输,最初通过网卡将数据包发送到指定的服务器。
服务器 Runtime 接管到申请之后,会首先调用本地的 Stub 依照约定好的协定格局进行解码,最初调用服务端具体的函数。函数执行结束,把后果利用本地的 Stub 编码之后通过 runtime 发送给客户端。客户端 Runtime 接管到音讯利用本地 Stub 进行解码,而后进行其余解决。
由此可见,古代的 rpc 框架其实是把协定的封装和数据的发送别离形象成了独自的层。Stub 负责协定局部,Runtime 解决数据发送以及网络相干局部。
网络数据传输
数据通过网络传输过程中,每个数据包的完整性如何来辨认,如果是一个简略 int 型数据很简略,然而如果是一个类或者一个数组,甚至是其余变长的类型,rpc 的通信协议如何束缚这些,如果能正确辨认进去数据是协定局部最难解决的局部。更何况还有大头小头编码的问题。
但凡基于网络传输的模式,任何通信都是不牢靠的,网络实质是不牢靠的。包含网络抖动,谬误等造成的丢包,粘包景象,如何正确的解决也是一个 rpc 通信中很重要的局部。一个 rpc 申请失败,是间接抛弃还是重试,这些策略都须要去规定。
性能
一个 rpc 调用如果采纳同步的形式,性能会大大打折扣,如何实现 rpc 的异步调用,这是一个 rpc 是否优良的重要指标。
无论 rpc 的网络传输如许优良,都会有性能损耗,是否把某些后果数据设置缓存?
无论是 client 还是服务端,解决申请的线程是否重用(线程池)?
是否反对多语言呢?
socket 虽易,RPC 却难
更多精彩文章
- 分布式大并发系列
- 架构设计系列
- 趣学算法和数据结构系列
- 设计模式系列