Remote Procedure Call (RPC)
RPC 是一种基于 Client-Server 的通信框架,让 Client 可以 locally call function,经由 RPC 框架处理、发送后,在 Server-side 处理请求,由 Server 将运算结果发送回 Client.通常来说,client-side 和 server-side 的调用 syntax 都是相同的,就好像他们是在同一台机器上。
从实现上来说,编译器通过 Interface Definition Language (IDL) 自动处理 RPC 框架的代码,在 Client-side 编译出 Stub,在 Server-side 编译出 Skeleton,这样 client 在调用函数的时候,client-side 的 stub 就会自动 marshall 调用参数,然后发送到 server-side.
| 术语 | 解释 |
|---|---|
| Stub | 由 IDL 编译而来,被 link 进程序;将调用参数转换为 bit strings 并通过网络发送 |
| Skeleton | 由 IDL 编译而来,被 link 进程序;将接收到的 bit string 重新转换为调用参数 |
| Marshall | 打包参数,并处理不同的数据格式,如 Byte Ordering |
RPC Procedure
下面,我们来看一次 RPC Call 的完整流程
- client 调用 client stub.这是一次 local call,将调用参数放到栈上
- (Marshalling) client stub 将参数打包进 message,并且通过 RPC Runtime 调用一次 system call 以发送 message
- 操作系统发送 message,RPC Runtime 进行 blocked 状态以等待 server 返回执行结果
- server 上的 RPC Runtime 接收到了之后,将 message 传递给 server-side stub/skeleton
- (Un-marshalling) server-side stub 从 message 里解包出调用参数
- server 开始真正执行函数
当函数执行完毕后,返回结果会以同样的流程发送回 client.于此,一次 RPC Call 完成.如下圖所示

Multi-Threading
从上面的流程我们可以看出,RPC 也有一些问题:
- 在 client 等待 server 结果的时候,client 被 block 了
- client 有可能因为 message lost 或者 server 太慢/宕机,从而移植处于等待状态
- server 在处理 request 期间也是被 block 的
一种解决方法是使用多线程技术:
- 在 client 的一个线程等待 RPC reply 的时候,仍然可以做其他的事
- 让 server 可以同时处理多个 client 的 RPC request
多线程技术也带来两个新问题:
- 多线程程序很难测试、调试
- 资源共享方面,可能产生同步问题,可能需要加锁或者 semaphore 来保证数据安全和正确性.