• Home
  • 归档
文章检索 作品与友邻 关于我
暴君乔博客
Home 归档

rpc框架初入门槛

发布于: 2020-07-04
更新于: 2023-07-09
文章目录
  1. rpc
    1. 基本调用流程
    2. 传输协议
    3. IO 网络模型
    4. 协议设计姿势
    5. 序列化与反序列化
    6. 服务治理层
    7. 动态代理
    8. 主流 RPC 框架

rpc

Remote Procedure Call 远程方法调用,通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的思想

如果只看调用姿势,RPC 希望做到像调用本地方法一样调用远程服务。但实际上一次 RPC 调用背后至少包含:代理、编解码、网络传输、服务发现、负载均衡、超时重试、熔断降级等一整套链路。

基本调用流程

  1. 客户端通过动态代理拿到一个接口代理对象。
  2. 代理对象把方法名、参数类型、参数值等信息封装成请求。
  3. 请求经过序列化后,通过网络发送到服务端。
  4. 服务端反序列化请求,根据服务名和方法名找到本地实现。
  5. 服务端执行本地方法,把结果或异常再序列化返回。
  6. 客户端收到响应后反序列化,最终返回给业务代码。

传输协议

传输协议决定数据怎么在网络上传输,常见选择有:

  • TCP:性能稳定、连接可复用,适合自定义二进制协议,也是很多 RPC 框架的基础选择。
  • HTTP/1.1:可读性和通用性好,调试方便,但文本协议和头部开销会更明显。
  • HTTP/2:支持多路复用、头部压缩、流式传输,gRPC 就基于 HTTP/2。
  • WebSocket:适合需要长连接、双向通信的场景,但在普通 RPC 里不是最主流选择。

如果是内部高性能调用,可以优先考虑 TCP 或 HTTP/2;如果更看重生态、网关、调试和跨语言接入,HTTP/2、HTTP/JSON 会更舒服。

IO 网络模型

RPC 框架的吞吐量和延迟,和 IO 模型关系很大。

  • BIO:一个连接一个线程,模型简单,但连接数上来后线程开销大。
  • NIO:非阻塞 IO,通过 selector 管理多个连接,适合高并发场景。
  • AIO:异步 IO,由操作系统完成后通知应用,但 Java 生态里实际使用没有 NIO 普遍。

Java RPC 框架里常见的是基于 Netty 的 Reactor 模型:少量线程负责连接、读写事件和编解码,再把业务执行丢给独立线程池,避免 IO 线程被业务逻辑阻塞。

协议设计姿势

自定义 RPC 协议通常会把消息拆成 header 和 body:

  • 魔数:快速判断是不是当前协议,避免收到脏数据。
  • 版本号:协议升级时做兼容。
  • 序列化类型:标识 body 使用 JSON、Hessian、Protobuf 等哪种格式。
  • 消息类型:区分请求、响应、心跳、异常等。
  • 请求 ID:用于异步调用时把响应和请求对应起来。
  • 数据长度:解决 TCP 粘包、半包问题。
  • Body:真正的方法调用参数或返回结果。

简单示意:

magic | version | serializer | messageType | requestId | bodyLength | body

协议设计要尽量稳定,字段要能扩展,长度要明确,异常要可表达,最好还要支持心跳和连接空闲检测。

序列化与反序列化

序列化负责把对象转成网络可传输的字节,反序列化则负责把字节还原成对象。技术选型可以从性能、体积、可读性、跨语言、兼容性几个角度看。

技术 优点 缺点 适合场景
JSON 可读性好,调试方便,生态成熟 体积偏大,性能一般,类型表达较弱 对外接口、调试友好场景
Hessian 使用简单,体积比 JSON 小 跨语言生态一般 Java 内部服务调用
Protobuf 性能好、体积小、跨语言强 需要维护 IDL,字段变更要遵守兼容规则 多语言、高性能 RPC
Kryo 性能较好,Java 对象支持丰富 跨语言弱,版本兼容要小心 Java 内部高性能调用

如果是公司内部 Java 服务,可以选 Hessian、Kryo 这类上手快的方案;如果要跨语言或长期演进,Protobuf 这类 IDL 方案更稳。

服务治理层

RPC 不是只有一次请求响应,服务多起来后必须处理服务治理问题。

服务注册与发现

服务端启动后,把服务名、IP、端口、权重、版本等元数据注册到注册中心;客户端调用前从注册中心拉取可用服务列表,并缓存到本地。

常见注册中心有 ZooKeeper、Nacos、Consul、Etcd、Eureka 等。注册中心通常还会配合心跳和健康检查,把不可用节点及时摘掉。

负载均衡

当一个服务有多个提供者时,客户端需要选择其中一个节点发起调用。

  • 随机:实现简单,适合节点差异不大的场景。
  • 轮询:请求均匀分配,但不考虑机器性能差异。
  • 加权随机/加权轮询:给配置更高的机器更多流量。
  • 最少活跃调用:优先选择当前压力小的节点。
  • 一致性 hash:同一类请求尽量打到同一台机器,适合有本地缓存的场景。

集群容错策略

远程调用一定会遇到超时、网络抖动、服务异常,所以需要容错策略。

  • Failover:失败自动重试其他节点,适合读请求。
  • Failfast:失败立刻报错,适合非幂等写请求。
  • Failsafe:失败后吞掉异常,适合日志、监控这类旁路调用。
  • Failback:失败后后台定时重试,适合消息通知。
  • Forking:并行调多个节点,谁先返回用谁,适合对延迟极敏感但资源消耗更大的场景。

重试要特别注意幂等性,否则一次超时可能变成多次写入。

动态代理

业务代码通常只依赖接口,不直接写网络调用。RPC 框架会为接口生成代理对象,把本地方法调用转换成远程请求。

常见实现方式有:

  • JDK 动态代理:基于接口生成代理,简单直接。
  • CGLIB:通过继承类生成代理,适合没有接口的类。
  • Javassist/ByteBuddy:通过字节码生成代理,性能和灵活性更强。

代理层一般会负责读取方法信息、组装请求、发起网络调用、等待响应、处理异常和超时。

主流 RPC 框架

框架 特点
Dubbo Java 生态常见,服务治理能力强,支持多协议、多注册中心
gRPC Google 开源,基于 HTTP/2 和 Protobuf,跨语言能力强
Thrift Facebook 开源,IDL 驱动,跨语言支持好
Motan 微博开源,轻量级 Java RPC 框架
Spring Cloud OpenFeign 更偏 HTTP 声明式调用,和 Spring Cloud 体系结合紧

简单总结:RPC 的重点不是“远程调用”这四个字,而是围绕远程调用把性能、稳定性、治理能力和研发体验都补齐。

rpc框架初入门槛
/archives/702d7132/
作者
tyrantqiao
发布于
2020-07-04
更新于
2023-07-09
许可协议
CC BY-NC-SA 4.0
赏

蟹蟹大佬的打赏,大家一起进步

支付宝
微信

扫一扫,分享到微信

微信分享二维码
MySQL执行计划详解
如何计算mysql表空间大小
© 2026 tyrantqiao 本站总访问量次 本站访客数人次 载入天数...载入时分秒...
  • 文章检索
  • 作品与友邻
  • 关于我

展开标签

  • 随笔
  • 旅行
  • Java
  • 面经
  • 源码
  • 架构
  • Hadoop
  • 计算机网络
  • 技术
  • IDEA
  • maven
  • JDK
  • Linux
  • MySQL
  • 性能
  • 数据库
  • Redis
  • MQ
  • Spring
  • SquirrelFin
  • 记账
  • Android
  • 个人财务
  • TIDB
  • unity
  • chatgpt
  • 前端
  • Vue
  • Git
  • shadowsocks
  • Hexo
  • 问题排查
  • 业务
  • JVM
  • 算法
  • nginx
  • ssh
  • Python
  • 爬虫
  • test
  • vim
  • 影视剧
  • 中间件
  • 事务
  • 表达
  • 运动
  • mybatis
  • 域名
  • AI
  • 产品
  • 家装
  • 土巴兔
  • github
  • 软件
  • 个人项目
  • Leaves
  • 幽默
  • 穿搭
  • 画画
  • 缓存
  • 摄影
  • 设计模式
  • c
  • 课程设计
  • 调酒
  • 数学

Collection

作品与友邻

我做的小工具、朋友的站点和一些长期值得回访的灵感来源。

  • 土 土巴兔 AI 导购交互演示 可点击体验用户导购、平台运营、装修公司、材料商及 AI 话术知识库的多端增长流程。 /demos/tubatu-ai-guide/
  • L Leaves 行程记录 我做的行程记录页面小工具,用来沉淀旅行路线、日程安排和途中的灵感。 https://leaves.tyrantqiao.com/
  • 本 本网站主题yilia设计者的主页 http://litten.me/
tyrantqiao的头像

tyrantqiao

github rss qq mail facebook linkedin

About

关于我

代码、海浪和持续折腾,都是生活的一部分。

<div class="aboutme-card"> <p class="aboutme-eyebrow">tyrantqiao</p> <h3>Java 全栈开发</h3> <p>常年和 Java、后端服务、前端工程、数据与部署打交道,喜欢把复杂问题拆开、写清楚,也把踩坑过程整理成文章留给后来的人。</p> <div class="aboutme-tags"> <span>Java</span> <span>Full Stack</span> <span>Backend</span> <span>Frontend</span> <span>Extreme Sports</span> </div> <p>工作之外偏爱冲浪等极限运动,享受在浪上找平衡,也享受在代码里找边界。</p> <div class="aboutme-contact"> <a href="mailto:[email protected]">Gmail</a> <a href="mailto:[email protected]">QQ Mail</a> </div> </div>