一 进程间通信
远程服务调用(RPC)在计算机科学中已经存在超过四十年时间,但仍然对不少程序员来说,还是一个模糊的概念。RPC 出现的目的,就是为了能够与调用本地方法一样去调用远程方法。
先看一段简单的 Java 代码
public static void main(String[] args){
System.out.println("hello world")
}
运行这段代码要完成下面四个工作:
a 传递方法参数
b 确定方法版本
c 执行被调用方法
d 返回执行结果
上面的调用者和被调用者在一个进程中,如果它们在两个进程中,应该怎么处理呢?这就变成了进程间(IPC)的通信问题。
通常,有以下几种解决方案来解决 IPC 问题
- 管道或具名管道
- 信号
- 信号量
- 消息队列
- 共享内存
- 本地套接字
二 通信的成本
最初计算机科学家们的想法,就是将 RPC 作为 IPC 的一种特例来看待,这个观点,在今天看来,仅从分类上说也仍然是合理的,只是到具体操作手段上就不合适了。
1987 年,在“透明的 RPC 调用”一度成为主流范式的时候,有人提出了一系列的质疑。
- 两个进程通信,谁作为服务端,谁作为客户端?
- 怎样进行异常处理?异常该如何让调用者获知?
- 服务端出现多线程竞争之后怎么办?
- 如何提高网络利用的效率?连接是否可被多个请求复用以减少开销?是否支持多播?
- 参数、返回值如何表示?应该有怎样的字节序?
- 如何保证网络的可靠性?调用期间某个链接忽然断开了怎么办?
- 发送的请求服务端收不到回复怎么办?
中心思想就是:把本地调用与远程调用当做同样的调用来处理,这是犯了方向性错误,把系统间的调用透明化,反而会增加程序员工作的复杂度。
之后,一众计算机专家总结了通过网络进行分布式运算的八宗罪。
- 网络是可靠的
- 延迟是不存在的
- 带宽是无限的
- 网络是安全的
- 拓扑结构是一成不变的
- 总会有一个管理员
- 不必考虑传输成本
- 网络都是同质化的
以上八条反话被认为是程序员在网络编程中经常忽略的八大问题,潜台词就是如果远程调用要透明化,就必须为这些罪买单。这算是给 RPC 能否等同于 IPC 来暂时定下了一个具有公信力的结论。
到此,RPC 应该是一种高层次的或者说语言层次的特征,而不是像 IPC 那样,是低层次的或者说系统层次的特征的观点成为为工业界、学术界的主流观点。