接口基础概念:RESTful API、SOAP、gRPC 等常见接口协议简介

说到接口协议,很多初级开发容易搞混,觉得都是发请求拿数据,没什么区别。其实不然,协议的选择直接决定了接口的性能、调试难度和后期维护成本。我这些年遇到的线上问题,十有八九都跟协议理解不到位有关——选错了协议,排查起来那叫一个痛苦。

这一章,我把工作中最常见的三种接口协议拎出来,跟大家拆开揉碎讲清楚。说白了,就是帮你建立一张“什么时候该用谁”的地图。

先看一张图,让你对这几种协议有个整体观感。这也是我平时做架构设计时,脑子里会浮现的框架。

常见接口协议对比框架 常见接口协议 RESTful API SOAP gRPC 基于资源 · HTTP 动词 无状态 · JSON/XML 严格规范 · XML 消息 高性能 · Protobuf 序列化 选型核心思想 对外公开 → RESTful 最灵活 金融/企业级 → SOAP 最安全 内部微服务 → gRPC 最高效

RESTful API —— 最通用的选择

RESTful 是我平时打交道最多的协议,没有之一。它本质上是一套架构风格,核心思想是“资源导向”——你把一切业务数据都看作资源,URL 就是资源的路径,HTTP 方法就是操作资源的动词。

举个例子:GET /api/users/123 表示“获取用户 123 的信息”,POST /api/users 表示“创建一个用户”。简单、直观,前端工程师看一眼 URL 大概就知道在干什么。

我个人的习惯是:在设计 RESTful 接口时,先把业务资源清单列出来,再定义每个资源的 CRUD 操作。这样结构清晰,后期排查问题也方便——哪里出错了,看路径和动词基本能猜个八九不离十。

我在项目中遇到过:有个同学把所有的操作都塞进了 POST /api/doAction,用请求体里的 type 字段区分增删改查。结果接口文档写了一整页,排查日志时完全看不懂。其实就是没用对动词。

RESTful 的典型特征:基于 HTTP/HTTPS,使用 JSON 或 XML 传输,无状态(每个请求独立),资源通过 URI 唯一标识。

避坑指南

我曾经踩过一个坑:路径参数中用了大小写混写,结果安卓和 iOS 端的 URL 大小写不一致,线上出了好几个 404。后来我强制团队遵守全小写命名,世界清净了。

SOAP —— 严谨但笨重的老大哥

SOAP 是 Simple Object Access Protocol 的缩写,注意是“协议”,不是“风格”。它有严格的消息格式定义,必须用 XML 包装,还要包含 Envelope、Header、Body 这些固定结构。你想想看,光是消息体的签名和验证就够你写几大段代码的。

我记得在金融项目里,对接银行核心系统的支付接口,用的就是 SOAP。安全性确实高,支持 WS-Security 规范,但也真的很重。每次调个接口,先解析 WSDL 文件生成客户端代码,再构造 SOAP 信封,一条请求光序列化就要比 JSON 多花好几倍的时间。

SOAP 的优势在于:标准化程度极高,有完善的事务、安全、可靠性机制。所以常见于银行、保险、电信这类对安全性和规范性要求极高的行业。

我要特别提醒一下:如果你的接口只给内部服务用,别轻易上 SOAP。性能和开发效率上的代价真的很大。我之前见过一个团队,内部几个模块之间用 SOAP 通信,一次接口变更要同步改好几个地方,简直是灾难。

SOAP 消息示例(只看结构,不用深究细节):

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <auth:Authentication xmlns:auth="http://example.com/auth">
      <auth:Username>admin</auth:Username>
      <auth:Password>encryptedPass</auth:Password>
    </auth:Authentication>
  </soap:Header>
  <soap:Body>
    <m:GetUserInfo xmlns:m="http://example.com/user">
      <m:UserId>123</m:UserId>
    </m:GetUserInfo>
  </soap:Body>
</soap:Envelope>

gRPC —— 高性能的新贵

gRPC 是 Google 搞出的高性能 RPC 框架,基于 HTTP/2 传输,用 Protobuf(Protocol Buffers)做序列化。说白了,就是又快又省流量。

我强烈建议:如果你的项目是微服务架构,服务间调用频繁,那 gRPC 几乎是最优解。它支持双向流、流式传输,可以在一个连接上并行处理多个请求。我在一次实时风控数据上报项目中,把原来的 RESTful 接口改成 gRPC 后,延迟从 50ms 降到了 8ms,吞吐量提升了 4 倍。

但 gRPC 也有学习门槛。你得先定义 .proto 文件,用 protoc 编译器生成客户端和服务端代码。而且 gRPC 对浏览器不友好(虽然现在有 gRPC-Web,但还在发展),所以对外公开的接口还是 RESTful 更合适。

核心优势一句话总结:强类型、高性能、流式通信、自带服务健康检查。唯一的缺点就是不够通用(浏览器支持有限)。

简单的 .proto 定义示例:

// user.proto
syntax = "proto3";

service UserService {
  rpc GetUserInfo (UserRequest) returns (UserResponse);
}

message UserRequest {
  int32 user_id = 1;
}

message UserResponse {
  string user_name = 1;
  string email = 2;
  int32 age = 3;
}

生成代码后,调用就像本地函数一样:

UserServiceClient client = UserServiceGrpc.newBlockingStub(channel);
UserResponse response = client.getUserInfo(UserRequest.newBuilder().setUserId(123).build());
System.out.println(response.getUserName());

我在排查接口问题时发现:gRPC 的错误码是标准化的(如 UNAVAILABLE、DEADLINE_EXCEEDED),比 HTTP 状态码更贴合分布式场景。但调试工具链不如 RESTful 丰富,我一般用 gRPCurl 和 gRPCui 来做测试。

选型对比:一张表说清楚

怎么快速选型?我整理了一个对比表,你直接参考:

维度 RESTful SOAP gRPC
传输协议 HTTP/1.1, HTTP/2 HTTP, SMTP, JMS 等 HTTP/2
数据格式 JSON, XML XML Protobuf(二进制)
状态管理 无状态 支持有状态 无状态(连接复用)
性能 中等 低(XML 解析重) 高(二进制 + 流)
调试难度 低(浏览器直接调试) 高(需要 SOAP 工具) 中(需 gRPC 工具)
典型场景 对外 API、移动端服务 金融、政府、企业级系统 微服务内部、实时通信
我个人的看法 通用之王,80% 场景都够用 除非客户要求,否则不推荐 内部高效通信首选

注意:不要为了追求新技术而强行上 gRPC。如果你的接口主要面向公网浏览器用户,或者你的团队对 Protobuf 完全陌生,那先用 RESTful 快速交付,等稳定性验证通过后再考虑迁移。

协议本身没有的好坏,只有合适不合适。每次做技术选型,我都会问自己三个问题:谁在调用这个接口?数据量有多大?对延迟有多敏感?想清楚了,选型自然就明确了。