目录
介绍
RPC(Remote Procedure Call) 远程过程调用,是一种通过网络从远程计算机程序上请求服务的一种调用模型
- 利用该思想,可以让不同的服务间方法调用就像本地调用一样便捷,且不需要了解底层网络技术
- 简单来说,就是让A服务器上的a服务可以很方便地和B服务器上的b服务通信
看似高大上,其实它的底层流程和普通的网络通信(一个客户端通过 socket 发送数据、服务端接收并返回结果)差不多
但为什么会有RPC这样一个独立的概念?
- 核心区别不在于"是否用 socket 传输",而在于 抽象层次
区别
普通网络通信
开发者需要自己决定 消息格式 (怎么组织请求和响应)、序列化方式 (json/binary)、协议细节 (TCP/UDP/HTTP),以及在合适的地方进行网络传输(socket 读写)
RPC
RPC 的目标就是 让远程调用看起来像本地函数调用 ,所以它把网络通信这一堆繁琐的细节隐藏在 Stub(存根) 层里
一次rpc过程
历经了一次完整的网络请求)
客户端调用时 :写的是
result = add(3,5) --
背后实际上:由Stub 把函数名+参数序列化后通过 socket 发出去服务端收到时 :Stub 解析消息,找到对应的函数
add
,调用本地实现,把结果再打包返回客户端拿到结果:Stub 反序列化结果,交给调用方(就像函数返回值一样)
从涉及到的角色来看
- 客户端:服务调用方
- 客户端存根:存放服务端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务端
- 服务端存根:接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理
- 服务端:服务的真正提供者
总结

- 它的底层实际上就是普通网络通信
- 但 RPC 之所以叫 "RPC",是因为它把 底层网络通信 封装成了 函数调用,实现了"透明调用"的语义
RPC的功能实现
主要分为服务寻址、序列化和反序列化、网络传输功能三部分
服务寻址功能
引入
本地调用
只有一个上下文,符号表和函数体都在同一个地址空间,只要知道函数指针,就能跳转到函数体执行
远程调用
涉及到跨进程/跨主机,需要知道在哪台机器?哪个进程? 哪个函数?
确定实例
分布式系统里,同一个服务通常会有多个实例:
可能在不同机器上(IP 不同)
可能在同一机器的不同进程里(端口不同)
确定函数
在远程调用中,不同服务的地址空间不同,函数指针在另一台机器上没意义
- 即使两个进程在同一机器上,它们的虚拟地址空间也是隔离的,函数地址依然无用
- 因此,远程调用不能直接传递函数指针
解决方法
服务实例定位
静态配置
如果实例固定,可以在表中写死ip+端口,直接映射
服务发现机制
如果实例会变动(弹性扩/缩容、故障下线),就需要引入中介 -- 注册中心
- 保存当前可用的服务实例列表
服务发现分为两种模式,客户端发现(Client-side discovery)和 服务端发现(Server-side discovery / Load-balancer / API Gateway)
- 两者本质的区别,是在 "由谁来做负载均衡(选择实例)"上
客户端发现
客户端向注册中心查询 某服务的所有实例 ,由客户端本地使用某种负载均衡算法选择一个实例,直接发请求
优点
- 可以直接请求到目标实例,延迟小
- 负载均衡负担分散到各个客户端
- 客户端灵活
缺点
- 每个客户端(不同语言/框架)都要实现 discovery(服务发现) + LB(负载均衡)
- 如果客户端数量极大,注册中心会承受大量查询压力
- 客户端通常会缓存实例列表,以降低注册中心负载,若缓存 TTL 或更新机制不好,会出现短暂 stale(调用已经下线的实例或错过新实例)
服务端发现
客户端请求统一入口 ,入口组件从注册中心获取实例列表,选择一个并转发请求
优点
- 入口(LB/Proxy)可以做集中优化,在高并发场景下能更好地控制连接
- 可以在入口层做集中限流、熔断、路由规则,易于横向扩展入口层
缺点
- 多一跳,入口层可能成为额外的延迟来源(转发/队列/排队)
函数定位
为了解决函数地址失效的问题,RPC 引入 **方法 ID(Call ID)--**所有函数都有自己的一个ID,在所有进程中都唯一
- 客户端在做远程过程调用时会查表,找出调用方法对应的Call ID,然后传给服务端
- 服务端也会查表,找到对应的函数指针,然后执行相应函数的代码
序列化和反序列化功能
介绍
序列化:将消息对象转换为二进制流
反序列化:将二进制流转换为消息对象
必要性
在本地调用中,只需要将数据压入栈中,然后让函数去栈中读取即可
但远程调用涉及到数据的传输
- 由于客户端和服务端不在同一个服务器上,涉及不同的进程,不能通过内存传递参数
- 此时就需要让客户端先将请求参数转成字节流(编码),传递给服务端,服务端再将字节流转为自己可读取格式(解码),这就是序列化和反序列化的过程
- 反之,服务端返回值也逆向经历序列化和反序列化到客户端
(其实也就是网络传输的必要手段)
网络传输功能
过程
客户端将Call ID和序列化后的参数字节流传输给服务端,服务端执行调用逻辑后,将序列化后的调用结果回传给客户端
协议
主要有TCP、UDP、HTTP协议
(这块就不细说了,就是计网那些东西)
TCP和HTTP对比
基于TCP协议实现的RPC调用
- 直接在传输层上自定义协议
- 可以更灵活地对协议字段进行定制,更小的协议开销,可实现更高的性能和吞吐量
- 实现复杂,需要处理粘包、拆包、心跳、超时等问题,维护成本高
基于HTTP协议实现的RPC调用
- 在应用层使用 HTTP 作为传输载体
- 实现简单,跨语言兼容性强
- 协议封装层次多,头部开销大,传输效率略低于纯 TCP