真实面经题目 · 原创解析

RPC框架是怎么样的?

RPC 框架让调用远程服务像调用本地方法一样自然,但它本质上解决的是跨进程、跨机器调用中的寻址、编解码、网络通信、故障处理和治理问题。高质量回答要讲清动态代理、序列化、协议、服务发现、负载均衡、超时重试、熔断限流、链路追踪和幂等。

出现于:阿里巴巴 · 算法

60 秒回答模板

RPC 框架的核心目标是屏蔽远程调用细节,让业务代码以本地接口的方式调用远程服务。一次典型 RPC 调用是:客户端注入接口代理对象,方法调用被动态代理拦截,转换成包含服务名、方法名、参数、版本、请求 ID、超时时间等信息的请求;请求经过序列化和协议编码后,通过 Netty、HTTP/2 或 TCP 连接发送到服务端;客户端通常先通过注册中心做服务发现,再经过负载均衡选择一个可用实例。服务端收到请求后解码、反序列化,根据服务名和方法名找到具体实现,执行后把结果或异常序列化返回。成熟 RPC 框架还会处理连接池、心跳、超时、重试、熔断、限流、降级、链路追踪、鉴权和监控等问题。RPC 不是一个单点技术,而是一套分布式服务调用与治理体系。

考点 解决的问题
主线 客户端链路
易错点 只回答 RPC 就是远程过程调用,没有展开代理、协议、…

深入解析

01

解决的问题

RPC 即 Remote Procedure Call,远程过程调用。它的目标不是让网络消失,而是把远程调用封装成近似本地方法调用的编程模型。业务方只依赖接口,不需要在业务代码里手动拼 URL、建立连接、编码请求、处理响应。底层由框架承担服务定位、网络传输、序列化、协议、异常转换和治理能力。

02

客户端链路

客户端通常拿到的是代理对象,不是服务实现类。当业务代码调用接口方法时,代理会拦截调用,提取接口名、方法名、参数类型、参数值、版本号、分组、超时时间、请求 ID 等元信息,构造 RPC 请求。随后框架从服务发现模块获取实例列表,通过负载均衡选择目标机器,再把请求交给编码和传输层。

03

代理与 Stub

动态代理的作用是把本地方法调用转换成远程请求。传统 RPC 中的 Stub 可以理解为客户端本地存根,代表远程服务,负责参数打包、请求发送、响应解析和异常还原。服务端也有调用器,把网络请求分发到真实服务实现。现代框架可能不直接叫 Stub,但本质仍是客户端代理隐藏通信细节,服务端调用器隐藏方法分发细节。

04

序列化与协议

RPC 必须把内存对象转换成可在网络上传输的字节流,常见序列化方案有 JSON、Protobuf、Hessian、Kryo 等。协议定义字节流如何组织,例如请求头、魔数、版本号、序列化类型、消息类型、请求 ID、长度字段和消息体。协议设计要考虑粘包拆包、兼容性、压缩、心跳、错误码和扩展字段。

05

服务发现

在分布式环境中,服务实例会扩容、缩容、重启和故障迁移,客户端不能写死服务地址。RPC 框架通常依赖注册中心,服务端启动时注册服务名、IP、端口、版本、权重和元数据;客户端订阅服务列表变化并缓存可用实例。服务发现解决的是调用哪个实例的问题。

06

负载均衡与重试

客户端拿到多个服务实例后,需要负载均衡,常见策略包括随机、轮询、一致性哈希、最少活跃调用、按权重选择和基于延迟的自适应选择。超时是 RPC 必须有的保护机制,重试可以提高短暂故障下的成功率,但写请求如果没有幂等保障,可能造成重复扣款、重复下单或重复写入。

07

熔断限流

成熟 RPC 框架不只负责调用成功,还要在失败时保护系统。熔断用于下游持续失败或延迟过高时临时停止调用,快速失败或走降级逻辑;限流用于控制入口或下游调用速率;降级用于在非核心依赖异常时返回默认值、缓存值或简化结果,防止故障扩散。

08

可观测性

RPC 调用跨越多个服务后,排查问题会变得困难,因此需要链路追踪和监控。客户端发起请求时生成或透传 traceId、spanId、调用方、被调方、方法名、耗时、状态码等信息。监控指标通常包括 QPS、平均耗时、P95/P99 延迟、错误率、超时率、重试次数、熔断次数和线程池队列长度。

09

幂等与一致性

RPC 框架可以提供请求 ID、重试控制和超时机制,但不能自动保证所有业务幂等。超时不等于失败,客户端超时后服务端可能已经执行成功。如果此时盲目重试非幂等操作,就可能造成重复副作用。幂等通常需要唯一请求号、防重表、状态机、乐观锁、去重缓存或数据库唯一约束配合。

易错点

  • 只回答 RPC 就是远程过程调用,没有展开代理、协议、序列化、服务发现和治理链路。
  • 把 RPC 和 HTTP 简单对立起来,忽略 RPC 可以基于 HTTP/2,REST 也只是 HTTP 上的一种资源风格。
  • 认为超时就代表服务端没有执行,忽略服务端可能已经完成业务操作。
  • 认为重试一定能提高可用性,忽略非幂等写操作可能被重复执行。
  • 只讲客户端调用,不讲服务端如何解码、反序列化、查找方法、执行业务和返回异常。
  • 只关注性能,不提熔断、限流、降级、链路追踪、监控告警等线上治理能力。

面试官追问

RPC 为什么不能真的当成本地调用?

因为远程调用存在网络延迟、超时、部分失败、服务端执行成功但客户端未收到响应、序列化成本和版本兼容问题。本地调用是进程内调用,RPC 是不可靠网络上的分布式调用。

RPC 如何匹配请求和响应?

通常会在协议头中放入唯一请求 ID。客户端发送请求后把请求 ID 和 Future 或回调保存起来,服务端响应时带回同一个请求 ID,客户端再找到对应等待方填充结果或异常。

为什么 RPC 常用长连接?

长连接可以避免每次调用都进行 TCP 建连和释放,减少握手开销,提高吞吐和延迟表现。配合连接池、心跳和断线重连,可以稳定支撑高频服务间调用。

RPC 重试应该注意什么?

首先判断操作是否幂等,其次区分失败类型。连接失败相对适合重试;服务端已经开始执行但客户端超时,重试风险较高。还要设置最大次数、退避和重试预算。

RPC 和消息队列有什么区别?

RPC 通常是同步或准同步的请求响应模型,调用方关心结果;消息队列是异步解耦模型,生产者通常不等待消费者立即处理结果,适合削峰、异步处理和事件驱动。