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 的完整流程

  1. client 调用 client stub.这是一次 local call,将调用参数放到栈上
  2. (Marshalling) client stub 将参数打包进 message,并且通过 RPC Runtime 调用一次 system call 以发送 message
  3. 操作系统发送 message,RPC Runtime 进行 blocked 状态以等待 server 返回执行结果
  4. server 上的 RPC Runtime 接收到了之后,将 message 传递给 server-side stub/skeleton
  5. (Un-marshalling) server-side stub 从 message 里解包出调用参数
  6. 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 来保证数据安全和正确性.