RESTful与gRPC概述:背景与定义

聊到微服务架构,有个问题几乎绕不开:服务间到底怎么通信?

你想,拆成几十个甚至上百个服务之后,它们之间总要传递数据、调用接口。最主流的两个选择,就是RESTful和gRPC。我刚开始接触微服务时,也觉得这两个东西无非就是“一个用JSON,一个用二进制”。后来踩了几个坑才发现,背后的设计哲学差别挺大的。

这一章,我们先从背景和定义入手,搞清楚它们各自是什么、为什么会出现。

为什么我们需要对比它们?

先说背景。早期的单体应用里,所有模块都跑在一个进程里,方法之间直接调用,没有任何网络开销。后来业务复杂了,团队规模大了,单体变得越来越臃肿。大家开始把大应用拆成若干小服务,每个服务独立部署、独立开发。

问题就来了:服务A要调用服务B的数据,怎么办?

最简单的方案是HTTP + JSON,也就是RESTful的风格。但有些场景下,RESTful不够快,或者接口定义不够严谨。于是Google推出了gRPC,基于HTTP/2和Protocol Buffers,主打高性能、强类型。

核心矛盾:RESTful胜在简单、通用、生态成熟;gRPC胜在性能、效率、合约严格。选型不是非黑即白,得看场景。

RESTful:代表资源状态的表述性转移

RESTful的全称是Representational State Transfer,翻译过来挺拗口的——“表述性状态转移”。说白了,它是一种API设计风格,不是协议,也不是标准。

核心思想是什么呢?

  • 一切皆资源(Resource)。比如用户、订单、商品,都是一个资源。
  • 每个资源有唯一的URI标识。例如 /users/123 表示ID为123的用户。
  • 通过HTTP动词表达操作:GET获取、POST创建、PUT更新、DELETE删除。
  • 无状态。每次请求都包含所有必要信息,服务端不保存客户端状态。

我记得第一次用RESTful写接口时,最直观的感受就是“清晰”。一个URL对应一个资源,GET就是查,POST就是增,一眼就能看出这个接口是干嘛的。团队协作时,沟通成本很低。

一个小技巧:设计RESTful接口时,URI里尽量用名词复数形式,比如 /orders,不要用动词。动词留给HTTP Method去表达。

gRPC:高性能的远程过程调用框架

gRPC呢?它来自Google,是一个高性能、开源的RPC(Remote Procedure Call)框架。和RESTful不同,gRPC不依赖HTTP动词,而是让你像调用本地方法一样调用远程服务。

gRPC默认使用Protocol Buffers(简称Protobuf)作为接口定义语言(IDL)和序列化工具。你写一个 .proto 文件,定义好服务接口和消息结构,然后通过protoc编译器生成客户端和服务端代码。

// 一个简单的proto示例
service UserService {
  rpc GetUser (GetUserRequest) returns (User);
}

message GetUserRequest {
  int32 user_id = 1;
}

message User {
  int32 id = 1;
  string name = 2;
  string email = 3;
}

为什么gRPC性能好?原因有几点:

  • 基于HTTP/2,支持多路复用、头部压缩、服务器推送。
  • Protobuf序列化后的数据体积比JSON小很多,解析速度也更快。
  • 支持双向流、流式处理,适合实时通信场景。

我之前在做一个实时推荐系统时,用过gRPC做服务间调用。数据量一上来,JSON的解析开销就变得很明显。换成Protobuf之后,响应时间直接降了30%左右。嗯,这个差距在实际生产中是能感知到的。

注意一点:gRPC的调试和测试比RESTful要麻烦一些。你不能直接在浏览器里用curl或者Postman访问gRPC接口,需要专门的工具,比如grpcurl或BloomRPC。这是选型时容易被忽略的成本。

两者核心对比

下面这个表格,帮你快速抓住它们的本质差异:

维度 RESTful gRPC
底层协议 HTTP/1.1(也可用HTTP/2) HTTP/2
数据格式 JSON / XML / 文本 Protocol Buffers(二进制)
接口定义 无强制约束,靠文档约定 强类型,由proto文件定义
性能 中等,JSON解析有开销 高,序列化快、体积小
流式通信 需额外实现(如SSE) 原生支持(双向流)
浏览器支持 天然支持 需通过gRPC-Web转译
学习成本 低,大部分开发者都熟悉 中等,需学习Protobuf和工具链

看到这个表,你可能会想:“那是不是gRPC总是更好的选择?” 不一定。你想想看,如果你的上游是浏览器、移动端App,或者需要对接大量第三方系统,RESTful的通用性和易用性就特别重要。反之,如果是内部服务之间的高频调用、数据量大、对延迟敏感的场景,gRPC的优势就体现出来了。

知识体系总览

为了让你对本章内容有一个整体的印象,我画了一张结构图,把RESTful和gRPC的核心概念、定位以及选型的关键因素串起来。

RESTful 与 gRPC 知识体系总览 微服务间通信 RESTful gRPC HTTP动词 + URI 无状态 + JSON Protobuf + HTTP/2 双向流 + 强类型 选型决策因子 通用性 / 生态 性能 / 延迟 团队技能 客户端类型

从这张图可以看出,RESTful和gRPC并不是完全对立的关系。它们各自围绕不同的设计理念展开:RESTful强调资源与统一接口,gRPC强调合约与性能。选型时,需要综合考虑通用性、性能、团队技能、客户端类型等多个因素。

写在前面的话

好了,这就是第一章的内容。我不打算在一开始就告诉你“哪个更好”。因为在实际项目里,我见过有人用RESTful跑出了极好的性能,也见过有人用gRPC把自己折腾得够呛。工具本身没有的好坏,关键是你是否清楚每个工具最适合的战场。

接下来的章节,我们会深入协议细节、讲序列化效率、讲流式处理,还会拿出真实案例来分析选型成败。现在先把基础概念理清楚,后面就不容易跑偏。