1. 先让四个概念各就各位:它们本来就不在同一层
上周处理接口方案时,同事拿着新需求来找我,开口就是一句:“这次我们是不是要把 JSON 换成 gRPC?”我愣了两秒,因为这句话里藏着一个典型的层级错位。JSON 是一种数据编码格式,gRPC 是一整套 RPC 调用框架;真正能和 JSON 放在同一个赛道上比较的是 Protobuf,而真正能和 gRPC 放在同一个赛道里比较的往往是 REST 这类接口风格,不是 JSON。这个错位如果不纠正,后面所有讨论都会变成鸡同鸭讲。
类似场景在团队里出现频率很高。大家聊着聊着,就把 HTTP、gRPC、Protobuf、JSON 四个词揉成一团,仿佛它们是四种可以互相替代的“接口方案”。实际上它们根本不是一回事,只是平时总绑在一起出现,导致很多人误以为它们是同层概念。要把关系理清楚,第一步不是背定义,而是先把每个名字放进它该待的位置。
1.1 HTTP 是运输协议,不管 body 里装什么
HTTP 最核心的身份是“应用层传输协议”。它规定了客户端和服务端之间怎么建立请求、怎么返回响应、请求头和响应头里放什么、状态码代表什么意思,以及在 HTTP/1.1 里文本形式的请求行和头部怎么组织、在 HTTP/2 里二进制的帧和流怎么复用。
但 HTTP 完全不关心 body 里装的是什么。你可以在 body 里放纯文本、放 JSON、放 XML、放 Protobuf 编码后的二进制字节流,也可以放图片、放视频分片。HTTP 协议本身的职责是“可靠地把一段数据从 A 送到 B”,并且让双方都能理解请求的意图,比如 GET 表示获取、POST 表示提交、PUT 表示整体替换。它就像一条公路,公路上跑小轿车、跑卡车、跑冷链车都行,交通规则负责的是车辆怎么并线、怎么让行,不关心车厢里拉的是服装还是生鲜。
很多人之所以把“JSON 改成 gRPC”这句话说出口,其实是把“HTTP+JSON 的 REST 接口”整体当成了一个叫“JSON”的东西,然后再把“gRPC+Protobuf”的接口整体叫成“gRPC”。真正发生改变的是整个调用风格和传输组合,而不是单纯换了一个数据格式。如果只把 body 从 JSON 换成 Protobuf、其他地方不动,那得到的是一个“HTTP+Protobuf”的接口,并不是 gRPC。
1.2 Protobuf 和 JSON 才是同一赛道的两个选手
如果非要在四个概念里找一对真正的竞争对手,那就是 Protobuf 和 JSON。它们回答的是同一个问题:一份结构化数据,比如一个用户对象、一个订单列表,到底用什么形式编码后放进网络包或文件里。
JSON 的方案是文本化、自描述。字段名原样写在数据里,字符串用引号包起来,对象用花括号,数组用方括号,层次结构肉眼可见。优点是调试方便、跨语言支持极广、人类可以直接阅读;缺点是同样的字段名要在每个数据条目里反复出现,体积上天然冗余,而且它没有内建类型系统,数字精度、日期时间这些语义全靠各方约定。
Protobuf 的方案是二进制化、契约先行。它不把字段名放进每个消息里,而是把字段名编成编号,在 .proto 文件里统一约定。序列化后的数据是一串紧凑的字节,字段编号和值按特定规则排列。同样的数据,体积通常比 JSON 小不少,编解码性能也通常更快。代价是二进制不可读,没有 .proto 契约或者对应的反序列化代码,你面对一串字节基本等于面对天书。
打个比方,JSON 是快递单上直接写着“收货人:张三,电话:138xxxx,地址:某市某区某路几号”,所有信息贴在包裹外面,谁路过都能看懂。Protobuf 则是包裹上只有一个编号“A001”,具体名单和地址存在快递公司的系统里,系统里一查编号才知道这包裹送给谁。自描述有自描述的好处,但它在数据量放大之后必然付出更多重复成本;契约化有契约化的好处,但前提是收寄双方都维护好那份“系统”。
1.3 gRPC 是整套服务调用框架,不是单纯的数据格式
gRPC 的身份比前三个更重。它不只是数据怎么编码,也不只是数据怎么传输,而是把“服务的方法定义”“客户端怎么调用”“服务端怎么实现”“消息怎么序列化”“流式传输怎么做”“错误怎么返回”“超时和取消怎么传递”全部打包在一起的一套框架。
gRPC 的起点是 .proto 文件。你在这个文件里定义服务接口,例如一个 UserService,里面有一个 GetUser 方法,方法接收 GetUserRequest,返回 User。然后通过 protoc 工具生成客户端桩和服务端骨架代码。客户端代码看起来就像调用本地方法一样,实际上请求会经过 gRPC 库处理后,通过 HTTP/2 发送给服务端。
“通过 HTTP/2”这几个字很关键。gRPC 并没有发明一套全新的网络协议,它是建立在 HTTP/2 之上的。HTTP/2 提供了多路复用、二进制分帧、头部压缩这些能力,gRPC 在此基础上定义了消息帧格式、方法路径规则、状态码规范、元数据传输方式等。所以准确说,gRPC 与 HTTP 的关系不是替代,而是“寄生”和“扩展”。
如果还是用前面那道公路来类比,HTTP 本身只是公路和交规,JSON 是一辆普通厢式货车,Protobuf 是一辆标准集装箱车。gRPC 不是某辆车,而是一家物流公司。这家物流公司规定了自己的订单号格式、自己的装卸流程、自己的签收回执,然后它把货装进集装箱,用标准集装箱车在公路上跑。你问“这条公路是不是要改成集装箱车”?公路还是那条公路,只是跑在上面的运输体系从普通货车换成了物流公司的整套系统。
1.4 用一次快递场景把四者关系叠起来看
把抽象概念一次性全部装进大脑有点困难,我用快递场景做个整体折叠。HTTP 就是那套交通运输规则:规定卡车从哪个入口上高速、怎么出高速、超时了怎么处理。Protobuf 是一种标准集装箱,货物必须先按规则装进箱内,箱体本身紧凑、不怕风吹雨淋,但箱子里具体是什么,必须查箱单。JSON 是另一种包装方式,类似透明塑料袋加纸质面单,里面装着什么东西一眼就能看见,但体积大、易损坏、每件都要贴详细面单。gRPC 则是一家物流公司:它有固定的下
