想象你走进一家分工精细的餐厅:前台接待、传菜部、后厨热炒、面点房各司其职。这家餐厅接待两拨客人——大堂的散客看着印刷菜单,用自然语言报菜名,服务员把需求逐字抄在单子上传给后厨;而 VIP 包间的熟客则打一条专属热线,双方拿着同一张“订购表单”模板,报几个数字编号,后厨瞬间就知道要做什么。这里的“菜单点菜”就是 REST 风格:接口文档公开、报文是人类可读的 JSON 文本、每一单都完整自包含;而“表单热线”就是 gRPC:契约文件预先约定字段、报文用 Protocol Buffers 压缩成二进制、一条长连接上多路请求同时飞驰。微服务架构正是这样一家餐厅——订单、支付、库存各自是独立档口,档口之间如何高效传菜,直接决定了整桌菜的出品速度。本文就把这两条传菜通道的原理、差异与选型心法一次讲透。

岗位关联

对于 AI 从业者而言,理解 gRPC 与 REST 的选型逻辑,是构建高性能 AI 服务架构的基本功——无论是大模型推理服务还是特征平台,正确的通信协议往往比盲目堆算力更能立竿见影地降低延迟。

目录
  1. 可视化演示
  2. 通信协议概述
  3. REST技术特性
  4. gRPC技术特性
  5. 对比分析维度
  6. 选型决策指南
  7. 工程实践技巧
  8. 生态与未来
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

通信协议概述

餐厅的后厨从不直接面对客人,所有菜品都靠传菜通道送达。微服务架构也是如此——单体应用被拆成订单、支付、库存等多个独立“档口”后,档口之间必须通过网络互相调用:下单要通知库存扣减,支付要回调订单更新状态。这条看不见的“传菜通道”就是通信协议,它决定了消息传得多快、多稳、多省。

选对传菜方式,对于规模化的系统意义重大。如果每个档口之间都各自拉一条私人通道,服务数量一多,通道总数会爆炸式增长;更重要的是,通道的“报文格式”直接决定了每道菜在路上的耗时和成本。REST 和 gRPC 正是当前最主流的两种传菜方式:前者像大堂点菜,依赖 HTTP 方法与 JSON 文本;后者像 VIP 专线,依赖 HTTP/2 与二进制契约。

从数学上看,n 个服务两两直连时,潜在调用关系的数量增长得很快,这让“如何高效复用通道”成为必须正视的问题。

回看餐厅的比喻:档口越多,传菜路线越复杂,聪明的老板不会让每个档口都重新发明传菜方式,而是统一设计两类通道——公开的大堂点菜通道和高效的 VIP 专线。接下来我们分别拆解这两种通道的内部构造。

Cn=(n2)=n(n−1)2\displaystyle C_n = \binom{n}{2} = \frac{n(n-1)}{2}
这个公式刻画了微服务规模膨胀的速度:服务越多,潜在的通信连接数越接近平方级增长,通信协议的选择就越会放大或缩小系统整体成本。
  1. n 个服务参与协作的微服务独立进程数量,n 是任意正整数,代表系统规模。
    nn
  2. 组合数从 n 个服务里任选 2 个建立调用关系,组合计数给出全部可能连接的数量。
    (n2)\binom{n}{2}
  3. 化简结果组合数展开后除以 2,得到全连接场景下的连接数公式,直观暴露了规模瓶颈。
    n(n−1)2\frac{n(n-1)}{2}

REST技术特性

大堂点菜为什么流行?因为它“门槛极低”。菜单是公开印刷的,客人用自然语言就能交流,服务员把需求写成一张张独立的单子,后厨做完一单再处理下一单。REST 正是这套逻辑:它把业务数据抽象成“资源”,每个资源有一个 URL 地址,用 HTTP 方法表达操作意图——GET 是查看菜品、POST 是下单新菜、PUT 是整单替换、DELETE 是退菜。

REST 的报文载体通常是 JSON 文本。就像手写单子上的每一个字都清晰可辨,JSON 的字段名、层级结构对人和调试工具都完全透明,curl 一下就能看懂接口在传什么。与此同时,REST 强调无状态:服务员不记住你上一单点了什么,每一张单子都自包含全部信息。这对餐厅的好处是任何服务员都能随时接手,对应到系统就是服务器不保存会话,任意节点都能处理请求,横向扩容极其轻松。

REST 最大的“甜蜜负担”在于报文体积。每一次调用都要携带完整的 HTTP 头部和 JSON 文本,字段名反复出现,就像单子上每道菜都要把“宫保鸡丁,微辣,不要花生”写全。

大堂点菜胜在公开透明、人人能上手,但每张单子都“字斟句酌”地写全,传菜效率自然受限。当餐厅规模变大、点单频率变高时,老板开始思考:能不能给熟客开一条更高效的专线?

SREST=HHTTP+SJSON\displaystyle S_{\text{REST}} = H_{\text{HTTP}} + S_{\text{JSON}}
一次 REST 调用在网络上传送的字节数,等于 HTTP 头部元信息加上 JSON 正文。头部动辄数百字节,JSON 又因字段名重复而膨胀,高频调用下带宽成本非常可观。
  1. 单次报文总量REST 请求每次传输的总字节数,是头部与正文两部分之和。
    SRESTS_{\text{REST}}
  2. HTTP 头部方法、路径、状态、Cookie 等元信息组成的文本头,每个请求都会完整携带。
    HHTTPH_{\text{HTTP}}
  3. JSON 正文业务数据的文本载荷,字段名和结构冗余重复,数据量越大冗余越明显。
    SJSONS_{\text{JSON}}

gRPC技术特性

VIP 专线和堂食点单的本质区别,在于“先约定,后传输”。老板给熟客发一张印刷好的订购表单,第一栏填菜品编号、第二栏填数量,双方都清楚“编号 17 等于宫保鸡丁”。gRPC 就是这条专线:它要求客户端和服务端先共同维护一份接口契约文件(IDL,即接口定义语言,通常以 .proto 结尾),里面定义好每个服务的接口、参数和字段编号;随后用工具自动生成各语言的代码,就像把表单印刷并分发到每个档口。

gRPC 的底层是 HTTP/2,这条“热线”支持多路复用——一条长连接上可以同时跑很多个请求,互不阻塞;还支持头部压缩,把重复的元信息压缩到极小。报文本体用 Protocol Buffers(简称 Protobuf)编码为二进制:字段不再写名字,而是用数字编号代替,数据被紧凑地拼成字节流。同样的数据,Protobuf 的体积通常只有 JSON 的四分之一到十分之一。

专线还有一个堂食没有的王牌——双向流式通信。就像电话两端可以同时说话,gRPC 支持客户端和服务端在一条连接上持续互相推送消息,特别适合 AI 推理场景中逐 token 流式输出、或数据同步中的增量推送。表单专线把“每次都说全”变成了“一次约定、反复高效使用”。

r=SJSONSProtobuf≈4∼10\displaystyle r = \frac{S_{\text{JSON}}}{S_{\text{Protobuf}}} \approx 4 \sim 10
体积比 r 表示同一份数据用 JSON 编码比用 Protobuf 编码大多少倍。二进制省去了字段名和文本结构,换来的是传输更快、解析更快、带宽更省。
  1. 体积比值将同一数据分别编码,JSON 体积除以 Protobuf 体积,衡量压缩增益。
    r=SJSONSProtobufr = \frac{S_{\text{JSON}}}{S_{\text{Protobuf}}}
  2. 经验区间典型业务字段下,Protobuf 约为 JSON 的 1/4 到 1/10,故比值落在 4 到 10 之间。
    r≈4∼10r \approx 4 \sim 10

对比分析维度

大堂点菜和 VIP 专线各有拥趸,真正的工程判断要落到四个维度的对比上。第一是性能与体积:专线的 Protobuf 二进制报文小、解析快,HTTP/2 多路复用又让大量请求共享一条连接,吞吐与延迟全面占优;大堂的 JSON 虽体积大,但胜在直观。第二是可读性:REST 的报文人类可直接阅读,浏览器里就能调试,接口文档天然自解释;gRPC 的二进制报文肉眼不可读,必须借助工具解析 proto 契约。

第三是语言互操作:两边都支持主流语言,但 gRPC 靠契约文件自动生成各语言 SDK,就像把表单模板翻译成多国语言,一致性强;REST 则依赖各团队手写客户端,风格容易漂移。第四是浏览器支持:REST 被浏览器天然兼容,而 gRPC 依赖 HTTP/2 和自定义帧,浏览器无法直接发起,需要 gRPC-Web 或网关转换。

从并发模型看,两者的总耗时差异在请求密集时会被放大。REST 在 HTTP/1.1 下通常串行请求,总耗时是各请求之和;gRPC 在 HTTP/2 下并发复用连接,总耗时不超过最慢的那一路。

对比下来没有完美的点菜方式:专线快但“看不见”,大堂慢但“摸得着”。聪明的工程师不会二选一,而是让两种通道在各自的位置上发挥作用。

TgRPC≤max⁡i(Ti)≪∑i=1nTi=TREST\displaystyle T_{\text{gRPC}} \le \max_i(T_i) \ll \sum_{i=1}^{n} T_i = T_{\text{REST}}
并发请求的总耗时只取决于最慢的一路,而串行请求的总耗时是每路耗时相加。当调用次数 n 很大时,两者差距可相差数倍到数十倍。
  1. 单路耗时单个请求从发出到收到响应的完整时长,包含网络往返与服务端处理。
    TiT_i
  2. 并发上限多路请求同时发送时,整体耗时逼近其中最慢一路,而不是所有路累加。
    max⁡i(Ti)\max_i(T_i)
  3. 串行累加HTTP/1.1 下请求逐个排队,总耗时等于 n 个请求时长之和,差距由此而来。
    ∑i=1nTi\sum_{i=1}^{n} T_i

选型决策指南

选型本质上是在回答:你的“客人”是哪类?如果是内部档口之间的高频协作——比如订单服务反复查询库存、推荐引擎频繁拉取特征——那就像 VIP 熟客,用 gRPC 专线能省下大量带宽和延迟;如果是面向外部第三方开发者,比如开放平台、公开 API,那就像陌生散客,必须给他们一本看得懂的公开菜单,REST 的通用性和可读性无可替代。

性能敏感场景是 gRPC 的主场:高吞吐、低延迟、弱网环境,二进制小报文和连接复用都能明显改善体验。而兼容性要求高的场景,REST 的宽松约束反而是优势——JSON 天然允许字段可选,客户端与服务端可以各自缓慢演进;gRPC 的契约虽严格,但一旦变更就需要谨慎管理版本。团队技术栈同样影响决策:REST 工具链遍地都是,学习成本几乎为零;gRPC 需要团队理解 proto 契约、掌握代码生成和调试工具,初期投入更高。

把决策要素量化,可以写成加权评分的形式,分数越高越倾向选择 gRPC。

选型就像给餐厅定菜单:大堂菜单和 VIP 表单都印在墙上,关键是让对的客人走对的门。多数成熟团队的做法是“内外有别”——内部服务用 gRPC 提效,对外开放用 REST 保通用。

Score=w1×性能+w2×内部性+w3×契约需求−w4×学习成本\displaystyle \text{Score} = w_1 \times \text{性能} + w_2 \times \text{内部性} + w_3 \times \text{契约需求} - w_4 \times \text{学习成本}
选型评分 = 性能收益 + 内部调用收益 + 强契约收益 − 学习成本。权重 w 由团队根据实际情况设定,实质是在“效率红利”与“迁移代价”之间取平衡。
  1. 选型评分综合得分 Score 越高,越倾向选择 gRPC;得分越低则回归 REST。
    Score=w1×性能+w2×内部性+w3×契约需求−w4×学习成本\text{Score} = w_1 \times \text{性能} + w_2 \times \text{内部性} + w_3 \times \text{契约需求} - w_4 \times \text{学习成本}
  2. 正项权重性能要求高、调用发生在内部、需要强类型契约,都是 gRPC 的加分项。
    w1×性能+w2×内部性+w3×契约需求w_1 \times \text{性能} + w_2 \times \text{内部性} + w_3 \times \text{契约需求}
  3. 负项权重团队学习成本与既有生态改造代价是扣分项,权重 w4 通常取较小值。
    w4×学习成本w_4 \times \text{学习成本}

工程实践技巧

表单专线虽高效,但一旦表单印错,后厨就会做错菜。gRPC 的工程实践同样围绕“把契约管好”展开。首先,proto 文件要统一管理:就像餐厅把所有表单模板放在一个柜子里,团队应把 .proto 文件放入独立仓库,统一版本化发布,各服务通过依赖引入,避免各处复制造成契约漂移。

字段编号的兼容性是 gRPC 实践中最容易踩坑的地方。Protobuf 编码时,字段靠编号识别而非名字,因此编号一旦定下就像表单单号:只增不减、绝不复用。新增字段必须使用比当前最大编号更大的编号;删掉的字段编号要永久保留并标记为 reserved,否则未来某天复用旧编号,新旧客户端会互相解析错乱。

错误处理与观测同样关键。gRPC 定义了标准状态码(如 NOT_FOUND、UNAVAILABLE),服务端返回状态码而非随意字符串,调用方据此做精确重试;配合超时传播和链路追踪,一次跨服务调用从哪一环变慢都能被快速定位。表单维护得越规范,餐厅出菜的稳定性就越高。

新字段号≥max⁡(旧字段号)+1,已删编号⇒永久保留\displaystyle \text{新字段号} \ge \max(\text{旧字段号}) + 1, \quad \text{已删编号} \Rightarrow \text{永久保留}
字段兼容规则可概括为“只增不复用”:新字段号必须大于当前最大值,已删除的编号必须保留占位,这是保证滚动升级期间新旧服务互通的前提。
  1. 编号递增新增字段必须分配比当前所有字段号更大的编号,避免与旧字段冲突。
    新字段号≥max⁡(旧字段号)+1\text{新字段号} \ge \max(\text{旧字段号}) + 1
  2. 禁止复用已删除的字段编号不能再次分配,否则旧服务会把新字段误读成旧字段。
    已删编号⇒永久保留\text{已删编号} \Rightarrow \text{永久保留}

生态与未来

餐饮业不会停在纸质菜单和电话热线,通信协议同样在进化。云原生时代,gRPC 已成为服务网格(如 Istio、Envoy)中的一等公民:Kubernetes 集群内部的服务间通信大量采用 gRPC,网格侧车自动完成负载均衡、熔断与可观测性,专线变成了“智能总机”。

浏览器这道坎也正在被填平。gRPC-Web 规范让浏览器通过 HTTP/1.1 或 HTTP/2 与 gRPC 服务通信,配合 Envoy 等网关做协议转换,前端也能享受契约带来的类型安全。与此同时,HTTP/3 基于 QUIC 协议,在弱网环境下连接建立更快、队头阻塞更少,gRPC 未来有望平滑迁移到 QUIC 之上,专线在移动端和弱网场景会跑得更稳。

传菜通道的演化从未停止,但 REST 也不会退场。公开、可缓存、人类可读的价值在开放生态中依然稀缺,两种协议将长期并存、各司其职。对工程师而言,理解它们各自的底层逻辑,比追逐“谁取代谁”的争论重要得多。

AI 应用场景

大模型推理服务加速

阶段:模型部署与推理

解决的问题:LLM 推理是典型的流式高吞吐场景,传统 REST 轮询需要反复建立连接、逐次拉取完整 JSON 结果,token 级流式输出几乎无法实现。gRPC 的双向流式通信让客户端与服务端维持一条长连接,推理引擎逐 token 推送结果,首 token 延迟和带宽占用大幅下降。

具体案例:NVIDIA Triton Inference Server 等主流推理框架原生提供 gRPC 接口,AI 平台团队部署千亿参数模型时,客户端通过 gRPC 流式接口接收生成结果,配合 HTTP/2 多路复用支撑多路并发请求,将单路推理吞吐提升 2-3 倍。

内部特征服务平台

阶段:在线特征计算与获取

解决的问题:推荐系统每次请求需要同时拉取用户画像、物品特征、上下文特征等几十个特征,若用 REST 逐个请求则延迟累加严重。内部 RPC 框架基于 gRPC 契约先行、Protobuf 小报文的特点,一次并发调用即可聚合全部特征。

具体案例:某电商推荐团队将特征服务从 REST 迁移到 gRPC,proto 契约统一定义特征字段,特征量从平均 12KB 降到 1.5KB,P99 延迟从 180ms 降到 45ms,服务端连接数减少了 70%。

对外开放平台 API

阶段:AI 能力对外开放与集成

解决的问题:面向第三方开发者输出 AI 能力(如 OCR、语音识别、内容审核)时,外部调用方技术栈多样、期望低门槛接入,REST 的 JSON 可读性、浏览器兼容性和 HTTP 缓存能力是最大优势。

具体案例:某云厂商的 AI 开放平台对外提供 REST 风格接口,开发者通过 Swagger 文档即可调试,配合 API 网关完成鉴权、限流与计费;而平台内部的服务间调用则统一走 gRPC,形成“外部 REST、内部 gRPC”的经典分层。

Python 演示

python70 行
# -*- coding: utf-8 -*-"""REST(JSON) 与 gRPC(Protobuf 风格) 编码体积及传输耗时对比演示""" import jsonimport time  def encode_varint(value):    """把无符号整数编码为 varint 字节序列"""    out = bytearray()    v = value    while v > 0x7F:        out.append((v & 0x7F) | 0x80)        v >>= 7    out.append(v)    return bytes(out)  def make_field(field_no, wire_type, payload):    """生成 Protobuf 风格的字段:tag(字段号<<3|类型) + payload"""    tag = (field_no << 3) | wire_type    return encode_varint(tag) + payload  def proto_encode(user):    """将用户字典编码为极简 Protobuf 风格二进制消息"""    b = bytearray()    # 字段1: 用户ID(int64, wire_type=0)    b += make_field(1, 0, encode_varint(user['id']))    # 字段2: 姓名(string, wire_type=2, 长度前缀)    name = user['name'].encode('utf-8')    b += make_field(2, 2, encode_varint(len(name)) + name)    # 字段3: 邮箱(string)    email = user['email'].encode('utf-8')    b += make_field(3, 2, encode_varint(len(email)) + email)    # 字段4: VIP 标记(bool, wire_type=0)    b += make_field(4, 0, encode_varint(1 if user['vip'] else 0))    return bytes(b)  def json_encode(user):    """将字典编码为紧凑 JSON 文本"""    return json.dumps(user, ensure_ascii=False, separators=(',', ':')).encode('utf-8')  def simulate_invoke(n, protocol):    """模拟 n 次调用耗时:REST 串行,gRPC 单连接并发"""    if protocol == 'rest':        return n * 0.05          # 每次完整请求一个 RTT    return 0.05 + n * 0.002     # 一次握手 + 并发传输每请求耗时  def main():    user = {'id': 10086, 'name': '张三', 'email': 'zhangsan@example.com', 'vip': True}    p = proto_encode(user)    j = json_encode(user)    print('JSON 体积: %d 字节' % len(j))    print('Protobuf 体积: %d 字节' % len(p))    print('体积比: %.1f 倍' % (len(j) / len(p)))     n = 200    t_rest = simulate_invoke(n, 'rest')    t_grpc = simulate_invoke(n, 'grpc')    print('REST 串行 %d 次耗时: %.2fs' % (n, t_rest))    print('gRPC 并发 %d 次耗时: %.2fs' % (n, t_grpc))    print('耗时比: %.1f 倍' % (t_rest / t_grpc))  if __name__ == '__main__':    main()
目的:用约 100 行代码实现 Protobuf 风格的 tag-length-value 编码,与 JSON 编码对比体积,并模拟 REST 串行与 gRPC 并发调用的耗时差异,直观验证正文中的结论。
  1. def encode_varint(value):实现了 Protobuf 的 varint 变长编码,数值越小占用字节越少,这是二进制报文紧凑的核心。
  2. tag = (field_no << 3) | wire_type把字段编号和线类型合并进一个字节,让接收方能根据编号反查契约。
  3. b += make_field(2, 2, encode_varint(len(name)) + name)字符串字段采用“长度前缀 + 内容”的编码方式,解码时先读长度再读内容。
  4. json.dumps(user, ensure_ascii=False, separators=(',', ':'))生成去掉多余空格的紧凑 JSON,模拟生产环境的最小化输出。
  5. if protocol == 'rest': return n * 0.05模拟 REST 每个请求独占一次网络往返,n 个请求耗时线性累加。
  6. return 0.05 + n * 0.002模拟 gRPC 只在开始时握手一次,后续请求在同一条连接上并发传输。

常见误区

误区我听说 gRPC 性能碾压 REST,所以任何场景都应该优先用 gRPC,选 REST 就是落后。

正解gRPC 的优势体现在请求密集、报文较大、流式交互的场景。如果只是低频的小请求,比如每分钟调用几次且每次都只传一个 ID,REST 的简单直接反而更省心。就像只点一杯白开水,犯不上动用 VIP 专线——直接喊服务员反而最快。性能对比必须在具体负载模型下谈,脱离场景谈“碾压”没有意义。

为何常见:性能对比文章往往展示 gRPC 在压测中的巨大优势,读者容易忽略压测条件是高并发大报文,误把结论推广到所有场景。

误区Protobuf 和 JSON 差不多,只不过压缩了一下,换了个更紧凑的格式而已。

正解两者有本质区别。JSON 是自描述的文本格式,键名就在报文里,任何人拿到都能读懂;Protobuf 是依赖 schema 的二进制格式,报文里只有字段编号和值,没有契约文件(.proto)根本无法解析。就像一页填好数字的表单,不看表头模板,你根本不知道"17"是菜名还是数量。

为何常见:使用者看到 Protobuf“体积小、速度快”的表面特征,却没有意识到它“契约先行、编号定字段”的底层设计,导致在调试和版本演进时踩坑。

误区只有 gRPC 支持流式,REST 只能一请求一响应,做不了实时推送。

正解REST 生态也有流式方案,比如 SSE(Server-Sent Events)可以让服务端持续向客户端推送数据,HTTP 的 chunked 传输也能逐块返回内容。但它们是单向的、机制相对原始,无法实现客户端与服务端同时互发;gRPC 的四类流式模式(一元、服务端流、客户端流、双向流)是协议级的一等公民,实现复杂双向交互更优雅。

为何常见:很多人把“REST 默认不支持”误解成“REST 完全不能”,忽略了 HTTP 本身具备分块传输的能力,只是工程上用得少。

误区gRPC 也是基于 HTTP 的,浏览器里用 fetch 不就能直接调用了?

正解gRPC 依赖 HTTP/2 的二进制帧、Trailers 以及自定义的 gRPC 状态传递,浏览器原生的 fetch/XHR 无法构造这些帧,会被直接拒绝。要让浏览器调 gRPC 服务,必须借助 gRPC-Web 协议加 Envoy 等网关做转换,或者走 REST 兼容层。就像电话热线需要专用话机,浏览器这只“公共话筒”接不进专线。

为何常见:看到"gRPC over HTTP/2"就误以为它与普通 HTTP 请求等价,忽略了 HTTP/2 之上还有一层 gRPC 自定义的应用层协议。

误区反正 REST 报文人类可读,体积大点无所谓,带宽足够就万事大吉。

正解内部高频调用下,嵌套 JSON 很容易膨胀到 KB 级,字段名反复传输会显著消耗带宽和 CPU 解析时间。实测中,一个多层嵌套的用户对象 JSON 可以比 Protobuf 大 5-10 倍,当每秒调用上万次时,这直接转化为可观的机器成本和延迟。大堂点菜的单子写得太啰嗦,传菜阿姨也会累的。

为何常见:小规模系统里带宽冗余被低估,团队往往在流量上涨后才被迫优化,此时改造协议的成本已大幅提高。

面试题

Q1. gRPC 默认使用的数据序列化格式是?

单选题 · easy

  • A.JSON 文本
  • B.YAML 文本
  • C.Protobuf 二进制← 正确答案
  • D.XML 文本

答案:C。gRPC 默认使用 Protocol Buffers(Protobuf)作为序列化格式,它是一种依赖 schema 的紧凑二进制格式。JSON、YAML、XML 都是文本格式,体积更大、解析更慢。就像 VIP 专线用数字编号点菜而不是写全菜名。

Q2. gRPC 通信传输层基于的协议是?

单选题 · easy

  • A.HTTP/1.1 短连接
  • B.HTTP/2 长连接← 正确答案
  • C.WebSocket 全双工
  • D.裸 TCP 自定义帧

答案:B。gRPC 建立在 HTTP/2 之上,利用其多路复用、头部压缩和双向流能力。HTTP/1.1 不支持多路复用,WebSocket 与裸 TCP 都不是 gRPC 的传输底座。一条 HTTP/2 连接就像一条可多路并行的专线热线。

Q3. REST 中获取资源最常用的 HTTP 方法是?

单选题 · easy

  • A.GET 查询资源← 正确答案
  • B.POST 创建资源
  • C.PUT 全量更新
  • D.DELETE 删除资源

答案:A。GET 语义是安全且幂等地获取资源,是 REST 中最常见的查询方法;POST 用于创建、PUT 用于更新、DELETE 用于删除。就像大堂点菜时“查看菜单”是最基本的动作,对应 GET 查询。

Q4. Protobuf 中字段编号的核心作用是?

单选题 · mid

  • A.决定 JSON 键名
  • B.编码时标识字段位置← 正确答案
  • C.控制服务访问权限
  • D.记录字段修改日志

答案:B。Protobuf 编码时不传输字段名字,而是用字段编号在二进制流中标识“这是第几个字段”,接收端靠 .proto 契约把编号映射回字段名。字段编号一旦定下就只增不改,如同表单上的行号,行号一变整张表单就乱了。

Q5. gRPC 双向流式通信的核心特征是?

单选题 · mid

  • A.仅客户端连续发送
  • B.仅服务端持续推送
  • C.双方可同时收发数据← 正确答案
  • D.必须依赖 WebSocket

答案:C。双向流式通信允许客户端和服务端在同一条 HTTP/2 连接上同时、独立地发送多条消息,适合 AI 推理的流式输入输出。仅客户端发送是客户端流,仅服务端推送是服务端流,且 gRPC 不依赖 WebSocket。

Q6. 下列哪种场景更适合选用 gRPC?

单选题 · mid

  • A.对外公开的第三方开放接口
  • B.内部高吞吐的微服务调用← 正确答案
  • C.面向浏览器的静态页面站点
  • D.需要强缓存的多媒体接口

答案:B。内部高吞吐微服务调用是 gRPC 的典型主场——二进制小报文、连接复用、契约生成 SDK 都带来明显收益。对外接口需要通用性和可读性,浏览器场景需要 REST 的天然兼容,强缓存场景也依赖 REST 的 HTTP 缓存机制。

Q7. gRPC-Web 技术解决的核心问题是?

单选题 · hard

  • A.替代 HTTP/2 多路复用
  • B.让浏览器可调用 gRPC 服务← 正确答案
  • C.压缩 REST 请求报文体积
  • D.在浏览器端解析 JSON 更快

答案:B。gRPC 依赖 HTTP/2 二进制帧和 Trailers,浏览器原生无法构造,gRPC-Web 定义了浏览器可用的协议变体,配合 Envoy 等网关转换,让前端也能调用 gRPC 服务。它不替代 HTTP/2,也不负责压缩 REST 报文。

Q8. 下列属于 REST 风格核心特点的有?

多选题 · mid

  • A.报文内容人类可读← 正确答案
  • B.支持 HTTP 层缓存← 正确答案
  • C.强类型 IDL 契约
  • D.浏览器天然兼容← 正确答案

答案:ABD。REST 基于 JSON 文本,人类可读;利用 HTTP 缓存机制可减少重复传输;浏览器原生支持 REST 请求。强类型 IDL 契约是 gRPC 的典型特征,REST 恰恰缺少强制契约。这正是“大堂菜单”公开、通用、可缓存的特点。

Q9. gRPC 基于 HTTP/2 获得的核心能力包含?

多选题 · mid

  • A.单连接多路复用← 正确答案
  • B.HPACK 头部压缩← 正确答案
  • C.报文明文可读
  • D.双向流式传输← 正确答案

答案:ABD。HTTP/2 为 gRPC 带来多路复用(一条连接并发多个请求)、HPACK 头部压缩(减小元信息开销)和双向流式传输。报文明文可读是 REST/JSON 的特点,gRPC 的 Protobuf 报文是二进制不可直接阅读的。

Q10. 与 JSON 相比,Protocol Buffers 的特点有?

多选题 · hard

  • A.编码后体积更小← 正确答案
  • B.依赖 schema 契约← 正确答案
  • C.人类可直接阅读
  • D.序列化解析更快← 正确答案

答案:ABD。Protobuf 用字段编号替代字段名,省去大量文本冗余,体积通常只有 JSON 的 1/4 到 1/10,且二进制解析无需处理字符串结构,速度更快;但它依赖 .proto 契约,没有契约就无法解析,也不可读。人类可读是 JSON 的独特优势,就像印刷菜单人人能看,而填了数字的表单只有拿着模板的人才懂。