If I have seen further than others, it is by standing upon the shoulders of giants.
如果我看得比其他人更远,那是因为我站在巨人的肩膀上。
——艾萨克·牛顿(英国物理学家,1643-1727)
术语解释
RPC(Remote Procedure Call,远程过程调用)框架是一种技术思想,旨在让客户端能够像调用本地方法一样,无需关注底层网络细节即可调用远程服务器上的服务。
当我们在谈论 RPC 时,我们在谈论什么
如果说层层叠叠的网络协议技术让孤立的计算机能够相互通信,那么 RPC 技术则是在原本通信的基础上更加往前走了一步,我们使通信变得更加简单可用。
当我们回顾互联网的发展历史,不难发现,总有天才般的珠玉在前,它们前沿而充满了令人惊叹的早慧,但往往令人只能望而却步。但是随后又会有更多的天才参与其中,使之推广——或者说更加成熟可理解,让更多的开发者能够参与其中,从而让更多人能够参与到对互联网这一人类历史上最浩大的工程协作中来。
RPC 的核心思想
RPC(Remote Procedure Call,远程过程调用)框架是一种技术思想,旨在让客户端能够像调用本地方法一样,无需关注底层网络细节即可调用远程服务器上的服务。
以 Java 程序为例。
我们知道,一个程序要在计算机中执行,它首先要以一个进程的形式存在,也就是说,要从磁盘加载到内存中,由内核进行管理。
调用本地方法
// 本地函数
int calculateSum(int a, int b) {
return a + b;
}
// 在同一个程序中调用
void main() {
int result = calculateSum(5, 10); // 1. 直接调用
printf("结果是: %d\n", result); // 2. 获得返回值并使用
}
这里,在内核中实际上发生了如下结果。
- 程序从原本的磁盘中加载进入内存,成为了一个由内核管理的进程,具有完整的生命周期。
- 内核调用 Java 编译器进行了编译处理,生成了对应的 Java.class 字节码。
- JVM 运行该程序。JVM 与内核进行协议和沟通。
- 寄存器和 CPU 进行汇编语言层面的计算处理。
- 所有行为都在本地的内存空间(也就是内存条)中执行完毕,得到返回的结果。
可以看到,上述所有的操作都是在本机中运行的,虽然涉及到不少底层的原理,但是 JVM 都为我们隐藏起来了,实际上用户看到的直接是一个返回的结果。
一般远程通信
具体代码
一般来说,在不使用高级语言提供的框架时,我们需要自己来编写建构通信协议的具体对象,并交付给内核进行处理。一个进程一般监听一个端口,进程间的通信有多种方法,但是远程通信一般使用 socket(套接字)。
也就是说,我们具体要考虑和编写的内容如下:
- 使用 Java 的 Socket 类建立 socket 对象。否则我们需要通过 JNI 调用原生 socket API。
- 使用 Java 的序列化类将对象转为字节流。因为内核以及网络驱动中只处理字节数据(这仍然是一种抽象。在更底层,数据的本质实际上是一些电路信号)。
- 使用 Java 的 Buffer 类建立和配置缓冲区。socket 实际上也是一个位于内存中的进程,它的接收缓冲区和发送缓冲区同样需要内核为其分配内存大小,在等待到对应的中断信号切换至内核态时,会通过驱动与网络硬件进行数据交互。很直观的,缓冲区会影响单次数据传输的大小,从而间接影响到传输效率。
RPC 调用过程
// 在客户端代码中
// remoteCalculator 是 RPC 框架生成的一个代理对象
int result = remoteCalculator.calculateSum(5, 10); // 看上去和本地调用一模一样
printf("远程计算结果是: %d\n", result);

发表回复