通俗易懂的 RPC 原理与实践:从生活场景到技术实现 📅 发布时间:2026/8/20 22:13:22 👁 浏览次数: 一个阳光明媚的早晨老婆又在翻看我订阅的技术杂志。“老公什么是RPC呀为什么你们程序员那么多黑话”老婆还是一如既往的好奇。“RPC就是Remote Procedure Call的简称呀翻译成中文就是远程过程调用嘛”我一边看着书一边漫不经心的回答着。“啥你在说啥谁不知道翻译成中文是什么意思你个废柴快给我滚去洗碗”“我去。。。”我如梦初醒我对面坐着的可不是一个程序员为了不去洗碗我瞬间调动起全部脑细胞星辰大海在我脑中汇聚灵感涌现......是这样远程过程调用自然是相对于本地过程调用来说的嘛。“嗯哼那先给老娘讲讲本地过程调用是啥子”“本地过程调用就好比你现在在家里你要想洗碗那你直接把碗放进洗碗机打开洗碗机开关就可以洗了。这就叫本地过程调用。”“哎呦我可不干那啥是远程过程调用”“远程嘛那就是你现在不在家跟姐妹们浪去了突然发现碗还没洗打了个电话过来叫我去洗碗这就是远程过程调用啦”多么通俗易懂的解释我真是天才“哦我明白了”说着老婆开始收拾包包。“你这是干啥去哦”“我我要出门浪去呀待会记得接收我的远程调用哦哦不咱们要专业点应该说待会记得接收我的RPC哦”......温馨提示非程序员请就此止步程序员请继续往下阅读......一、RPC 的科学解释说起RPC就不能不提到分布式这个促使RPC诞生的领域。1.1 从本地调用到远程调用假设你有一个计算器接口Calculator以及它的实现类CalculatorImpl那么在系统还是单体应用时你要调用Calculator的add方法来执行一个加运算直接new一个CalculatorImpl然后调用add方法就行了这其实就是非常普通的本地函数调用因为在同一个地址空间或者说在同一块内存所以通过方法栈和参数栈就可以实现。现在基于高性能和高可靠等因素的考虑你决定将系统改造为分布式应用将很多可以共享的功能都单独拎出来比如上面说到的计算器你单独把它放到一个服务里头让别的服务去调用它。这下问题来了服务A里头并没有CalculatorImpl这个类那它要怎样调用服务B的CalculatorImpl的add方法呢1.2 RPC 的核心思想有同学会说可以模仿B/S架构的调用方式呀在B服务暴露一个Restful接口然后A服务通过调用这个Restful接口来间接调用CalculatorImpl的add方法。很好这已经很接近RPC了不过如果是这样那每次调用时是不是都需要写一串发起http请求的代码呢比如httpClient.sendRequest...之类的能不能像本地调用一样去发起远程调用让使用者感知不到远程调用的过程呢像这样Reference private Calculator calculator; ... calculator.add(1,2); ...这时候有同学就会说用代理模式呀而且最好是结合Spring IoC一起使用通过Spring注入calculator对象注入时如果扫描到对象加了Reference注解那么就给它生成一个代理对象将这个代理对象放进容器中。而这个代理对象的内部就是通过httpClient来实现RPC远程过程调用的。可能上面这段描述比较抽象不过这就是很多RPC框架要解决的问题和解决的思路比如阿里的Dubbo。1.3 RPC 要解决的两个核心问题解决分布式系统中服务之间的调用问题。远程调用时要能够像本地调用一样方便让调用者感知不到远程调用的逻辑。二、RPC 的实现原理2.1 传输协议的选择实际情况下RPC很少用到http协议来进行数据传输毕竟我只是想传输一下数据而已何必动用到一个文本传输的应用层协议呢我为什么不直接使用二进制传输比如直接用Java的Socket协议进行传输2.2 RPC 的完整过程不管你用何种协议进行数据传输一个完整的RPC过程都可以用下面这张图来描述以左边的Client端为例Application就是rpc的调用方Client Stub就是我们上面说到的代理对象也就是那个看起来像是Calculator的实现类其实内部是通过rpc方式来进行远程调用的代理对象至于Client Run-time Library则是实现远程调用的工具包比如jdk的Socket最后通过底层网络实现实现数据的传输。2.3 序列化与反序列化这个过程中最重要的就是序列化和反序列化了因为数据传输的数据包必须是二进制的你直接丢一个Java对象过去人家可不认识你必须把Java对象序列化为二进制格式传给Server端Server端接收到之后再反序列化为Java对象。下一次我也将通过代码给大家演示一下如何实现一个简单的RPC。三、RPC 与其他技术的对比3.1 RPC vs Restful其实这两者并不是一个维度的概念总得来说RPC涉及的维度更广。如果硬要比较那么可以从RPC风格的url和Restful风格的url上进行比较。比如你提供一个查询订单的接口用RPC风格你可能会这样写/queryOrder?orderId123用Restful风格呢Get /order?orderId123RPC是面向过程Restful是面向资源并且使用了Http动词。从这个维度上看Restful风格的url在表述的精简性、可读性上都要更好。3.2 RPC vs RMI严格来说这两者也不是一个维度的。RMI是Java提供的一种访问远程对象的协议是已经实现好了的可以直接用了。而RPC呢人家只是一种编程模型并没有规定你具体要怎样实现你甚至都可以在你的RPC框架里面使用RMI来实现数据的传输比如DubboDubbo - rmi协议四、RPC 框架的复杂性要实现一个RPC不算难难的是实现一个高性能高可靠的RPC框架。4.1 服务发现与负载均衡比如既然是分布式了那么一个服务可能有多个实例你在调用时要如何获取这些实例的地址呢这时候就需要一个服务注册中心比如在Dubbo里头就可以使用Zookeeper作为注册中心在调用时从Zookeeper获取服务的实例列表再从中选择一个进行调用。那么选哪个调用好呢这时候就需要负载均衡了于是你又得考虑如何实现复杂均衡比如Dubbo就提供了好几种负载均衡策略。4.2 性能优化与缓存这还没完总不能每次调用时都去注册中心查询实例列表吧这样效率多低呀于是又有了缓存有了缓存就要考虑缓存的更新问题blablabla......4.3 其他高级特性你以为就这样结束了没呢还有这些客户端总不能每次调用完都干等着服务端返回数据吧于是就要支持异步调用服务端的接口修改了老的接口还有人在用怎么办总不能让他们都改了吧这就需要版本控制了服务端总不能每次接到请求都马上启动一个线程去处理吧于是就需要线程池服务端关闭时还没处理完的请求怎么办是直接结束呢还是等全部请求处理完再关闭呢......如此种种都是一个优秀的RPC框架需要考虑的问题。当然接下来我们还是先实现一个简单的RPC再在上面一步步优化传送门 如何实现一个简单的RPC五、总结RPC作为分布式系统的核心技术之一其核心价值在于让远程服务调用像本地调用一样简单透明。从生活化的比喻到技术实现我们看到了RPC如何通过代理模式、序列化、网络传输等机制将复杂的远程通信细节封装起来为开发者提供简洁的编程接口。在实际应用中一个成熟的RPC框架还需要考虑服务发现、负载均衡、容错处理、性能优化等诸多方面。理解RPC的基本原理有助于我们更好地使用和设计分布式系统。六、参考资料wikipedia - RPCwhat-is-restful-rest-vs-rpcdifference-between-rpc-and-rmi.htmlwhat-is-the-difference-between-java-rmi-and-rpcDubbo 使用文档Dubbo 源码开发手册一本很棒的分布式书籍《大型网站系统与Java中间件实践》