{T}

如何理解 RPC 远程服务调用?

0. 引言

微服务架构下,服务之间互相调用——调用方希望"像调用本地方法一样调用远程服务",这就是 RPC(Remote Procedure Call,远程过程调用)。RPC 的难点在于:屏蔽网络差异(序列化、传输、编解码)、自动定位服务(注册中心)、处理故障(超时、重试、熔断)。本文拆解 RPC 的四要素与一条完整调用链。

1. RPC 要解决的核心问题

图表渲染中…
要素作用典型实现
动态代理让调用方无感:接口 → 代理对象 → 网络调用JDK Proxy、Javassist、ByteBuddy
序列化协议对象与字节流的互转,决定性能与兼容性JSON、Hessian2、Protobuf、Kryo
网络传输连接管理与 IO 模型Netty(TCP)、HTTP/2(gRPC)、QUIC
服务发现/路由找到目标实例、负载均衡注册中心 + 负载均衡策略

2. 一条 Dubbo 调用的完整链路

图表渲染中…
  • 接口契约:Provider 与 Consumer 共享接口 jar(或同构接口),保证参数/返回值一致;
  • 协议:Dubbo 3.x 默认 Triple 协议(tri://,基于 HTTP/2 + Protobuf),兼容 gRPC;旧版默认 Dubbo 协议(TCP);
  • 集群容错:Failover(默认,重试其他节点)、Failfast、Failsafe、Failback、Forking;
  • 超时与重试timeout + retries,注意重试要幂等(写操作重试可能重复下单)。

3. RPC vs HTTP 接口

维度RPC(Dubbo/gRPC)HTTP REST
性能高(二进制协议、长连接、连接复用)中(文本协议、短连接开销)
协议Dubbo/Triple/gRPC 二进制HTTP/1.1、HTTP/2、JSON
服务治理内置(注册发现、负载均衡、熔断、限流)需配套网关/注册中心
跨语言gRPC 好(Protobuf),Dubbo 以 Java 为主天然跨语言
适用服务间内部调用(BFF 以下)对外 API、异构系统集成、浏览器

实践共识:内部服务用 RPC(性能 + 治理),外部接口用 HTTP(兼容 + 规范)。gRPC 是"跨语言 + 高性能"的折中,已成为云原生 RPC 事实标准(K8s 生态、Google API)。

4. 序列化选型要点

协议性能体积跨语言场景
JSON调试方便、对外接口
Hessian2部分Dubbo 传统默认
ProtobufgRPC、高性能内部调用
KryoJava 内部高性能场景

序列化安全提示:反序列化是不可信输入——避免使用 Java 原生序列化(ObjectInputStream)处理外部数据,历史上有大量反序列化 RCE 漏洞。

5. 面试高频问题

  1. RPC 和 HTTP 的区别? 见上表——本质差异是"二进制协议 + 长连接 + 服务治理内置" vs "文本协议 + 通用";
  2. 为什么 RPC 需要注册中心? 实例动态上下线,调用方需要实时可用的实例列表做负载均衡与故障转移;
  3. RPC 超时怎么处理? 超时 + 重试(幂等才重试)+ 熔断降级 + 异步化;
  4. 如何保证 RPC 安全? 内网隔离 + 认证(token/mTLS)+ 限流 + 参数校验。

6. 小结

  • RPC 四要素:动态代理、序列化、网络传输、服务发现
  • Dubbo 调用链:接口 → 代理 → 序列化 → Netty → 反序列化 → 执行 → 返回;
  • 内部服务用 RPC(Dubbo/gRPC),对外用 HTTP REST;
  • 超时重试必须幂等,序列化要防注入。

下一章讲解为什么微服务需要 API 网关:路由、鉴权、限流与灰度发布。