八股文解析
RPC 和 HTTP 调用有什么区别?微服务里怎么选?
一句话结论
RPC 是面向服务调用的二进制通信协议,HTTP 是面向资源的文本协议;微服务内部优先 RPC,对外暴露优先 HTTP。
面试标准答法
1. 本质差异:通信模型 vs 协议形态
RPC(Remote Procedure Call) 的核心思想是让远程调用看起来像本地调用。它屏蔽了网络细节,客户端调用一个本地方法,底层自动完成序列化、传输、反序列化、服务寻址。关键点:
- 传输层:通常基于 TCP(也有 UDP/HTTP 变体),但 RPC 的协议头是自定义二进制格式(如 Dubbo 协议头 16 字节,含 magic、serialization id、status、request id 等字段)
- 序列化:采用紧凑二进制(Hessian2、Protobuf、Kryo),体积小、解析快
- 连接管理:长连接 + 连接池,避免频繁三次握手
- 服务发现:依赖注册中心(Nacos/Zookeeper),客户端本地缓存服务列表,通过负载均衡(随机/轮询/一致性哈希)选择节点
- 超时与重试:客户端可配置超时时间,失败后自动重试(需注意幂等性)
HTTP 调用 是标准的请求-响应模型,基于 HTTP 协议(文本协议)。关键点:
- 协议头:ASCII 文本,包含 method、path、headers、body
- 序列化:通常是 JSON/XML,可读性强但体积大
- 连接管理:HTTP/1.1 支持 keep-alive 复用连接,但HTTP/2 才真正支持多路复用(stream 概念)
- 服务发现:通常通过 DNS + 负载均衡器(Nginx/LB),或服务网格(Istio)的 sidecar 代理
- 语义:自带 GET/POST/PUT/DELETE 等 HTTP 方法,天然对应 CRUD 操作
2. 核心机制对比
| 维度 | RPC(以 Dubbo 为例) | HTTP(以 Spring Cloud 为例) |
|---|---|---|
| 协议格式 | 自定义二进制头 + 序列化 body | 文本协议(HTTP/1.1)或二进制帧(HTTP/2) |
| 序列化 | Hessian2/Protobuf(平均 100-200 字节) | JSON(平均 500-1000 字节) |
| 连接方式 | 长连接池,连接复用率 90%+ | HTTP/1.1 keep-alive,HTTP/2 多路复用 |
| 性能 | 单次调用 RTT 约 0.5-2ms | 单次调用 RTT 约 2-10ms(含 HTTP 头解析) |
| 服务发现 | 注册中心(Nacos/ZK),客户端直连 | DNS/LB,或网关路由 |
| 负载均衡 | 客户端内置(权重/最小活跃数) | 服务端负载均衡(Nginx/LB) |
| 超时控制 | 客户端显式配置(如 3s) | 依赖 HTTP 层或网关配置 |
| 可观测性 | 需额外集成(如 SkyWalking) | 天然支持 HTTP 状态码、日志 |
| 跨语言 | 需支持多语言 SDK(如 gRPC 支持多语言) | 任何语言天然支持 |
| 调试 | 需工具(如 Postman 插件) | 浏览器/curl 直接调试 |
3. 微服务里的选择逻辑
内部服务间调用(北向流量):优先 RPC
- 性能敏感:高 QPS 场景下,RPC 的二进制协议 + 长连接能节省 30%-50% 的带宽和延迟
- 服务治理:RPC 框架(Dubbo/gRPC)内置熔断、限流、降级、链路追踪,无需额外组件
- 强类型约束:通过 IDL(Interface Definition Language)定义接口,编译期校验,避免运行时类型错误
对外暴露(南向流量):必须 HTTP
- 客户端兼容性:浏览器、移动端、第三方系统只认 HTTP/HTTPS
- 标准语义:RESTful 风格天然适合资源型接口,便于缓存、CDN 加速
- 防火墙穿透:HTTP 端口(80/443)通常不会被防火墙拦截,RPC 自定义端口可能被阻断
混合架构(主流实践):
外部客户端 → API 网关(HTTP) → 内部服务(RPC 调用) → 下游服务(RPC)网关负责协议转换(HTTP → RPC),内部服务间全部走 RPC。典型如:Spring Cloud Gateway(HTTP)→ Dubbo 服务(RPC)。
常见追问
| 追问 | 回答要点 |
|---|---|
| 「RPC 一定比 HTTP 快吗?」 | 不一定。HTTP/2 多路复用 + Protobuf 序列化后,性能差距缩小到 10%-20%。RPC 的优势在于连接复用和协议头精简,但如果是低频调用(如管理接口),HTTP 足够 |
| 「gRPC 是 RPC 还是 HTTP?」 | gRPC 是 RPC 框架,但底层走 HTTP/2 协议。它用 HTTP/2 的 stream 承载二进制帧,既保留了 RPC 的高效,又获得了 HTTP/2 的多路复用和流式传输能力 |
| 「如何保证 RPC 调用的幂等性?」 | 幂等性靠业务层实现,与协议无关。常用方案:客户端生成全局唯一 requestId,服务端通过 Redis/DB 去重;或使用状态机保证重复请求返回相同结果 |
| 「RPC 框架如何做服务发现?」 | 客户端启动时从注册中心拉取服务列表并缓存,订阅变更通知。客户端直连模式(Dubbo)比代理模式(Istio)延迟更低,但控制面复杂度更高 |
面试回答模板(30 秒版)
延伸准备
- HTTP/2 对 RPC 的冲击:HTTP/2 的多路复用 + 头部压缩(HPACK)让 HTTP 协议的性能接近二进制 RPC。可以对比 gRPC(基于 HTTP/2)和 Dubbo(基于 TCP 自定义协议)的选型差异,体现对协议演进的认知。
- 服务网格(Service Mesh)下的协议选择:Istio/Linkerd 默认支持 HTTP/1.1、HTTP/2、gRPC,但对 Dubbo 自定义协议支持有限。如果团队用服务网格,需要考虑 RPC 框架的协议兼容性,或改走 gRPC。
- 序列化选型对比:JSON(可读性)、Protobuf(性能+压缩比)、Hessian2(Java 生态兼容性)、Kryo(极致性能但需注册类)。能说出每种序列化的适用场景,说明你对 RPC 底层有深入理解。
想系统备战大厂大模型/Agent 开发?NiceOffer 提供 SDE+LLM 双轨 1v1 陪跑,合同保底 40w 年薪,文末扫码咨询。