网络编程笔记 RPC

最近复习了一下网络编程,顺便学习一下有所听闻的RPC.

最近 又重新写起了 Python,做的第一件事情就是检查一下 Emacs 的 Elpy. 检查结果倒是没有什么问题,不过有另外一个问题. Elpy 到底是怎么运作的呢,它的项目代码结构表明语法解析工作是一个用 Python 写的 RPC 服务器做完成的.于是我回归 Python 的第一件事情就是了解 RPC 的相关细节.不过此之前,我复习了网络编程的相关知识,主要是 Python Socket API 的使用以及 TCP/UDP 的相关概念,以后有空会对这一块再进行总结的.

注意

  1. 这篇笔记不会涉及一句代码,就跟我看过有关于 HTTP 协议的书一样不偏重于编码,主要是 RPC 的一些概念和一些特征, 只有这样,才能够明白别人的代码为何这么写.
  2. 这篇总结我不能百分百保证没有错,但我保证肯定不是最全的,也不太可能会总结全.如果想知道冰山的其它几个角还是要去读 "TCP/IP详解 第一卷" 这本书和相关 RPC 的书籍,比如 "Unix Network Programming 第二卷"(我也没读过就是了).

什么是RPC 全名为 Remote Procedure Call, 意为"远程过程调用".是一类协议(protocols),一类模型(models),一类 机制(mechanisms), 随便你怎么叫.跟它的名字一样, RPC 可以用来远程调用过程, RPC 服务器提供函数, RPC 客户端则是 调用服务器提供的函数. RPC 客户端会把你想要调用哪个过程和相关参数封成一个网络报文发送到服务器上面, RPC 服务器接收 这个报文并且对进行解析,执行服务器上的对应过程,把过程的返回值封成报文返回给 RPC 客户端.

RPC的特征 这是在 "Foundations of Python Network Programming" 上列出的特征的总结.

  1. 所有 RPC 服务器对传递的数据会有限制.通用的 RPC 服务器会有更多的限制,因为这类型的 RPC 服务器是服务于多种编程语言的. 如果只是针对于特定编程语言的 RPC 服务器,可以传递的数据限制就没那么多.
  2. 所有 RPC 服务器具备提示异常的能力.当 RPC 客户端调用的过程发生错误的时候, RPC 服务器要返回错误信息.就像写本地程序一样.
  3. 许多 RPC 服务器提供 introspection, 也就是检查 RPC 服务器提供哪些过程.当然只是许多 RPC 服务器提供而已.
  4. 所有 RPC 服务器都需要提供一些定位方案(addressing scheme), 也就是客户端是怎么跟 RPC 服务器通讯并且连接到特定的远程 API.
  5. 部分 RPC 服务器支持认证机制,访问控制,甚至有的还要求不同的客户端需要不同的凭证(credentials)来访问.这些可以通过使用像 HTTP 协议实现 RPC 来轻易的得到这些支持.这说明了 RPC 可以工作于任何协议层上.

那么RPC能用来做什么呢 既然已经概了解 RPC 的能力后,就要考虑能用来做什么,由于本人也是刚接触 RPC, 所以只知道以下几个.

  1. 混合编程,你可以利用 RPC 来协调 Lisp 和 Python 来进行工作, Elpy 就是其中一个例子.当然了,只要你想到的编程语言 都可以.
  2. 与不可靠协议协作,如 UDP, RPC 负责超时和重传的工作.
  3. 用于分布式开发

RPC的实现 这一块单纯用代码做为例子的话,可能要写很多代码,而且也不够通用.因为不同的语言有不同的工具,不同的实现可能会相 差比较大.比如 Elpy 的 RPC Server 就没有用到一点网络编程,仅仅是靠系统的 Pipe 来实现一套 RPC 服务器和客户端.而 Foundation of Python Network Programming 则是在 HTTP 层上实现的 RPC 服务器以及客户端.

不过它们有一个共同点,那就是离不开 IPC. RPC 就是 IPC 的一种形式, request-response 的工作方式.HTTP 也是这种方式. 至于 IPC, 这里就不多说了,想必读这篇笔记的人应该是能最低限度地知道什么是 IPC.

如果想了解如何实现 RPC 的话,我个人建议,先大概了解 RPC 是做什么的,有什么特性,也就是有什么一般的约定,换句话说就是协议. 然后根据你的惯用语言来找简单的例子来入门,假如你用 Python 的话,那么 Foundation of Python Network Programming 3rd Edition 的第 18 章就有一些不错的例子.

打个比方,可以想象一下一些 WEB API 的使用情况.做为客户端,发送请求到指定 URL, 在这个请求中,还可能包含一些参数;做为 服务端,要为为这种 URL 设定返回过程,比如 Django 里面,一个 URL 对应一个函数或者方法,该过程可以返回 JSON,XML 等数 据给客户端. RPC 也是差不多,当然协议上是不一样的,在 RPC 里面,请求的不一定是 URL, 得到可能是其它的数据格式.如果是在 HTTP 协议层上实现的 RPC, 你可以简单的把它看做一个 Web Server. 调用的 remote procedure 也不过是一个 URL, 返回的数据基本与 HTTP 通信所使用的数据无异, RPC Server 所做的不过就是绑定一个 URL 和 一个 Procedure 而已. 根据不同的数据类型划分为两种协议, XML-RPC 和 JSON-RPC, 实现的时候要根据协议和结合 RPC 相关特性,这就是实现 RPC 的思路.

两个协议的链接

  1. JSON-RPC协议
  2. XML-RPC协议

一个RPC-like例子

Pseudo JSONRPC

Author: saltb0rn (asche34@outlook.com)

Date: 2018-06-16

Emacs 28.2 (Org mode 9.5.5)

Validate