1. SOAP(基于 XML 的老牌 Web Service)
是什么
SOAP 起源于早年的 Web Service 远程调用体系,常跑在 HTTP(也可以是 SMTP 等协议)之上,消息格式严格使用 XML,接口契约通常由 WSDL 描述。它的核心是“消息 + 契约 + 规范完备”。
今天的地位
在互联网应用里基本退场,但在部分传统企业/政务/银行等遗留系统、ESB 总线里仍能见到。知道它是什么已足够,大多数新项目不会再选。
优点
- 规范完备:WSDL、XSD、WS-*(安全、事务、可靠消息)一应俱全。
- 强约束、强治理:跨组织对接时“说不清接口”的概率低。
缺点
- 笨重:XML 体积大、解析慢、学习与调试成本高。
- 生态老化:浏览器端、移动端支持差,现代云原生不友好。
何时考虑
- 只能对接遗留系统或上游强制要求 SOAP/WSDL 时。
2. RESTful(最流行的资源风格)
是什么
基于 HTTP 的资源建模风格,强调使用 HTTP 动词(GET/POST/PUT/DELETE)对应 CRUD,无状态(Stateless),响应常用 JSON(也可 XML 但已少见)。
优点(文稿要点 + 补充)
- 简单、轻量、上手快,与浏览器/移动端/网关/CDN 天然契合。
- 无状态:扩容简单,水平伸缩友好。
- HTTP 生态加持:缓存、幂等、条件请求、范围请求、状态码等“拿来就用”。
缺点(文稿要点 + 补充)
- 缺乏统一强制标准:需要借助 OpenAPI/Swagger 等做契约文档与校验。
- 表达复杂操作不自然:超越“资源”的业务动作常需自定义动词或子资源。
- 版本管理容易分裂:路径版(/v1 /v2)、Header 版、参数版,多版本并行要治理。
- N+1 请求:前端聚合多个资源时,可能出现多次往返。
落地实践
- 使用 OpenAPI 3 定义契约,自动生成 SDK/Mock/文档(Swagger UI)。
- 资源建模清晰:名词化 URI、用 HTTP 状态码表达语义。
- 幂等性:PUT/DELETE 应幂等;POST 创建可通过幂等键避免重复下单。
- 分页与筛选:统一 Query 约定(page/size/sort/filter)。
- 版本策略:新增字段默认向后兼容,避免破坏式变更;老版本设退网计划。
3. GraphQL(单端点、声明式查询)
是什么
由 Facebook 提出的 查询语言 与类型系统。客户端以查询语句“声明自己需要哪些字段”,服务端按需返回。通常单端点(/graphql)承载所有读写操作,返回 JSON。
文稿强调的能力
- 精准查询:请求中声明字段,避免 REST 的“字段过多/过少”。
- 强类型:Schema 描述对象、字段与参数类型,复杂结构可表达。
- 单端点:一个接口承载多种查询/变更,客户端换“查询语句”即可换能力。
- 自描述:可自省(introspection),客户端可发现可用类型与操作。
补充优缺点
- 优点
- 前后端协作效率高:前端自主组合所需数据,减少 N+1 往返。
- 工具链成熟:GraphiQL/Playground、Codegen、Apollo/Federation。
- 缺点
- 复杂度↑:Schema 设计、权限、指令、联邦网关均有学习曲线。
- 性能风险:不受约束的深度/广度查询可能压垮后端。
- HTTP 缓存困难:单端点 + 可变查询体,传统 CDN/浏览器缓存难命中。
- 监控与限流更细粒度:需要基于“字段/解析器”层面的可观测性。
落地实践
- 查询成本控制:深度/复杂度限制、白名单/持久化查询(Persisted Query)。
- 分页协议:推荐 Cursor 分页(Relay 规范)而非传统 offset。
- 缓存策略:客户端规范化缓存(Apollo/Relay),服务端可用 Response Cache 或查询指纹 + CDN。
- 安全与授权:字段级权限、数据隔离、N+1 通过 DataLoader 批处理。
- 联邦化:大型组织使用 Apollo Federation 聚合多子图。
适用场景
- 前端多端(Web/App/小程序)对数据裁剪的诉求强、接口频繁演化的 BFF 层。
4. RPC / gRPC(高性能、强类型的远程调用)
是什么
RPC(Remote Procedure Call)是调用远程函数像本地函数一样的范式,gRPC 是 Google 开源的主流实现,基于 HTTP/2 与 Protobuf。通过 IDL(.proto) 生成 客户端/服务端存根(Stub),多语言互通。
文稿要点
- 自动生成客户端与服务端代码,开发像调用本地方法。
- 高性能、强类型,主流语言支持健全。
- 不太适合对外公开 API:要求调用方接入 gRPC 生态,门槛高。
- 借助 HTTP/2 提供双向流能力。
补充
- 调用模型:Unary、Server Streaming、Client Streaming、Bidirectional Streaming。
- 传输效率高:二进制 编解码(Protobuf)更省带宽。
- 附带生态:拦截器、超时/重试、负载均衡、服务发现、可观测性良好(与服务网格契合)。
落地实践
- 契约优先:以 .proto 为单一事实来源,管控版本与兼容性(字段保留/弃用)。
- 幂等与重试:声明 idempotency,合理配置 deadline 与 backoff。
- 安全:mTLS、Auth 拦截器、跨数据中心传输加密。
- 网关:对外仍建议暴露 REST/HTTP+JSON;内部微服务间使用 gRPC。
- 链路追踪:结合 OpenTelemetry 注入 Trace Context。
适用场景
- 内部微服务之间高吞吐、低延迟调用;实时流式传输;多语言团队。
5. WebSocket(全双工长连接的实时通信)
是什么
浏览器与服务器之间建立长连接,支持全双工实时双向通信。非常适合消息推送、聊天室、协同编辑、看板/行情刷新等场景。
说明:文稿提到“WebSocket 不是 W3C 标准”。准确地说:WebSocket 协议是 IETF 的 RFC 6455;浏览器的 WebSocket API 由 W3C/WHATWG 制定。主流浏览器均已良好支持。
优点(文稿要点 + 补充)
- 实时推送:避免轮询,显著降低延迟与资源浪费。
- 跨域可用:配合反向代理与 CORS/同源策略正确配置。
- 支持二进制帧:比基于 JSON 的轮询更高效。
缺点(文稿要点 + 补充)
- 不适合简单请求-响应:这类还是 HTTP 更简单。
- 安全与稳定:需要心跳/保活、断线重连、授权续期、限流与背压处理。
- 伸缩与状态:需要 Sticky Session/外部状态(如 Redis)协调订阅关系。
落地实践
- 心跳/断线重连:客户端定期 ping;服务端空闲踢出,防资源泄漏。
- 鉴权与续期:连接时鉴权(URL 签名或 Header Token),过期后一键续签。
- 多节点广播:借助消息中间件/Redis PubSub/Fanout 同步频道。
- QoS:限频、消息积压监控、背压策略(丢弃旧帧/降采样)。
适用场景
- 强实时推送:IM、协同、监控大屏、交易撮合前端等。
6. WebHook(事件回调的“倒推”集成)
是什么
回调机制:A 系统在某事件发生时,主动调用 B 系统事先暴露的 HTTP 回调地址,通知“有事发生”。文稿中的例子:GitLab/GitHub 推送 Tag 触发 Jenkins 去拉代码、构建与发布,这正是 WebHook 的经典用法。
优点(文稿要点 + 补充)
- 简单直接、松耦合:无需订阅方轮询。
- 可扩展:多个系统注册回调即可获得事件。
缺点(文稿要点 + 补充)
- 可靠性:回调瞬时失败就丢了?需要重试队列、签名校验、幂等处理。
- 安全性:对外暴露端点,必须鉴权(HMAC 签名、IP 白名单、mTLS)。
- 可观测性:链路跨系统,排障需事件日志与重放工具。
落地实践
- 签名验证:发送方用密钥对 payload 计算 HMAC,接收方验签防伪造。
- 重试与退避:指数退避 + 最大次数;提供“死信队列/人工重放”后台。
- 幂等:事件 ID 去重,避免重复消费。
- 回调契约:版本与字段演进明确,拒绝“神秘 JSON”。
适用场景
- 系统间“有事我通知你”:CI/CD、支付回调、仓储/物流状态、第三方集成。
代码速览(片段级)
RESTful
GET /api/v1/users/123
200 OK
{"id":123,"name":"Alice","email":"a@example.com"}
GraphQL
query {
user(id: 123) { id name email }
}
gRPC(.proto)
syntax = "proto3";
service UserService {
rpc GetUser(UserRequest) returns (UserResponse);
}
message UserRequest { int64 id = 1; }
message UserResponse { int64 id = 1; string name = 2; string email = 3; }
WebSocket(握手与发送)
const ws = new WebSocket("wss://example.com/chat?token=...");
ws.onmessage = (e) => render(JSON.parse(e.data));
ws.send(JSON.stringify({type: "say", text: "hello"}));
WebHook(Node/Express 验签示意)
app.post("/webhook", express.raw({type:"application/json"}), (req,res)=>{
const sig = req.get("X-Signature");
const ok = verifyHmac(req.body, sig, process.env.SECRET);
if(!ok) return res.status(401).end();
const event = JSON.parse(req.body);
handle(event); // 幂等处理
res.sendStatus(200);
});
对比与选型
维度 | SOAP | RESTful | GraphQL | RPC/gRPC | WebSocket | WebHook |
---|---|---|---|---|---|---|
传输 | XML/HTTP | JSON/HTTP | JSON/HTTP | Protobuf/HTTP2 | 帧流/RFC6455 | JSON/HTTP(回调) |
接口形态 | 多端点、WSDL | 多端点、资源化 | 单端点 + 查询语句 | 方法化、IDL | 长连接、频道/会话 | 对方回调我 |
方向 | 请求-响应 | 请求-响应 | 请求-响应 | 请求-响应/流式 | 双向实时 | 事件驱动 |
优势 | 标准完备 | 简单通用 | 精准取数、强类型 | 高性能、多语言 | 实时推送 | 松耦合、无轮询 |
痛点 | 笨重过时 | 复杂动作表达弱 | 缓存/治理复杂 | 对外门槛高 | 伸缩与稳定 | 可靠性/安全 |
典型场景 | 遗留/政企 | 公共 API/BFF | 多端裁剪数据 | 内部微服务 | 聊天/行情/协作 | 支付/CI/CD/三方集成 |
组合拳建议
- 对外开放:RESTful(配 OpenAPI),订阅类事件补充 WebHook。
- 内部微服务:gRPC 为主,聚合层/外网边界提供 REST/JSON。
- 前端多端复杂聚合:在 BFF 层使用 GraphQL。
- 强实时:WebSocket。
- 遗留对接:被动支持 SOAP。
版本、文档、安全与可观测性(通用治理)
- 契约与文档
- REST:OpenAPI/Swagger;GraphQL:SDL + GraphiQL;gRPC:.proto + 文档生成。
- 版本与兼容
- 以“向后兼容优先”为原则,新字段默认可选;破坏式变更拉新版本并设退网计划。
- 安全
- 统一鉴权与配额:OAuth2/OIDC、API Key、mTLS;WebHook 必做签名与幂等。
- 可靠性
- 超时、重试、幂等键、熔断与限流;WebHook 做重试与回放;WebSocket 做心跳与背压。
- 观测
- 统一日志(结构化)、指标(QPS/错误率/延迟)、链路追踪(OpenTelemetry)。
结语
六种 API 风格各有取舍,没有“最好”,只有“最适合”。
如果只记一条:对外通用选 RESTful + WebHook,内部高性能走 gRPC,前端裁剪选 GraphQL,强实时用 WebSocket,遗留对接保留 SOAP。
结合你的业务形态、团队经验、性能与演进需求,制定一套可治理、可演化的 API 策略,落地时把契约、版本、鉴权、幂等、观测这几件事做好,就能少走弯路。