原文地址:http://mp.weixin.qq.com/s/lkz3zGk-KyMkI1eYeYH4ng
RPC(Remote Procedure Call),即远程过程调用,是一个分布式系统间通信的必备技术,本文体系性地介绍了 RPC 包含的核心概念和技术,希望读者读完文章,一提到 RPC,脑中不是零碎的知识,而是具体的一个脑图般的体系。本文并不会深入到每一个主题剖析,只做提纲挈领的介绍。
RPC 最核心要解决的问题就是在分布式系统间,如何执行另外一个地址空间上的函数、方法,就仿佛在本地调用一样,个人总结的 RPC 最核心的概念和技术包括如下,如图所示:
下面依次展开每个部分。
传输(Transport)
TCP 协议是 RPC 的 基石,一般来说通信是建立在 TCP 协议之上的,而且 RPC 往往需要可靠的通信,因此不采用 UDP。
这里重申下 TCP 的关键词:面向连接的,全双工,可靠传输(按序、不重、不丢、容错),流量控制(滑动窗口)。
另外,要理解 RPC 中的嵌套 header+body,协议栈每一层都包含了下一层协议的全部数据,只不过包了一个头而已,如下图所示的 TCP segment 包含了应用层的数据,套了一个头而已。
那么 RPC 传输的 message 也就是 TCP body 中的数据,这个 message 也同样可以包含 header+body。body 也经常叫做 payload。
TCP 就是可靠地把数据在不同的地址空间上搬运,例如在传统的阻塞 I/O 模型中,当有数据过来的时候,操作系统内核把数据从 I/O 中读出来存放在 kernal space,然后内核就通知 user space 可以拷贝走数据,用以腾出空间,让 TCP 滑动窗口向前移动,接收更多的数据。
TCP 协议栈存在端口的概念,端口是进程获取数据的渠道。
I/O 模型(I/O Model)
做一个高性能 /scalable 的 RPC,需要能够满足:
-
第一,服务端尽可能多的处理并发请求
-
第二,同时尽可能短的处理完毕。
CPU 和 I/O 之间天然存在着差异,网络传输的延时不可控,最简单的模型下,如果有线程或者进程在调用 I/O,I/O 没响应时,CPU 只能选择挂起,线程或者进程也被 I/O 阻塞住。
而 CPU 资源宝贵,要让 CPU 在该忙碌的时候尽量忙碌起来,而不需要频繁地挂起、唤醒做切换,同时很多宝贵的线程和进程占用系统资源也在做无用功。
Socket I/O 可以看做是二者之间的桥梁,如何更好地协调二者,去满足前面说的两点要求,有一些模式(pattern)是可以应用的。
RPC 框架可选择的 I/O 模型严格意义上有 5 种,这里不讨论基于 信号驱动 的 I/O(Signal Driven I/O)。这几种模型在《UNIX 网络编程》中就有提到了,它们分别是:
-
传统的阻塞 I/O(Blocking I/O)
-
非阻塞 I/O(Non-blocking I/O)
-
I/O 多路复用(I/O multiplexing)
-
异步 I/O(Asynchronous I/O)
这里不细说每种 I/O 模型。这里举一个形象的例子,读者就可以领会这四种 I/O 的区别,就用 银行办业务 这个生活的场景描述。
下图是使用 传统的阻塞 I/O 模型。一个柜员服务所有客户,可见当客户填写单据的时候也就是发生网络 I/O 的时候,柜员,也就是宝贵的线程或者进程就会被阻塞,白白浪费了 CPU 资源,无法服务后面的请求。
下图是上一个的进化版,如果一个柜员不够,那么就 并发处理,对应采用线程池或者多进程方案,一个客户对应一个柜员,这明显加大了并发度,在并发不高的情况下性能够用,但是仍然存在柜员被 I/O 阻塞的可能。
$bAAMAAI{:B%J3{:((jbA3vjbv"jA3vj(B*r>r7*"rvvRǖ"r7*(}ф饵Y =I-9MUU
eM)UEYE%]9e E < )IT)(7*G3Tr/3ZjIAzrkJ3*G>>GIA0$</z/"_2X>7"_2[6?zvRǚzr7*(91h$




