客户端与服务器如何通信:HTTP/1.1、HTTP/2、REST、WebSockets、GraphQL、gRPC和Protocol Buffers完全手册

客户端与服务器如何通信:HTTP/1.1、HTTP/2、REST、WebSockets、GraphQL、gRPC和Protocol Buffers完全手册

💡 原文英文,约9600词,阅读约需35分钟。
📝

内容提要

本文深入探讨客户端与服务器通信的底层原理,涵盖TCP/TLS基础、HTTP/1.1至HTTP/3的演进、JSON与Protocol Buffers等数据格式,以及REST、GraphQL、WebSockets、SSE和gRPC等通信架构。文章分析各技术的设计动机、优缺点及适用场景,旨在帮助工程师根据系统需求做出合理的架构决策,而非盲目选择熟悉的技术。

🔎

延伸解读

协议选择的关键权衡

文章强调,选择通信方式应基于系统需求而非技术熟悉度。REST适合简单、可缓存的CRUD接口,但存在过度获取和N+1问题;GraphQL让客户端精确指定数据,但缓存困难且需防范复杂查询;WebSockets提供全双工实时通信,但连接管理复杂。理解这些权衡,才能做出合理的架构决策。

HTTP/2与HTTP/3的演进逻辑

HTTP/2通过二进制分帧、多路复用和HPACK压缩解决了HTTP/1.1的队头阻塞和冗余头部问题,但TCP层的队头阻塞依然存在。HTTP/3基于QUIC协议,在UDP上实现多路复用和快速连接,尤其适合移动网络和丢包环境。理解这些底层机制,有助于评估不同场景下的性能表现。

数据格式的隐性成本

JSON因其可读性和灵活性成为主流,但字段名重复传输和文本解析带来额外开销。Protocol Buffers通过二进制编码和预定义模式,显著减少数据体积和解析时间,但需要模式管理和代码生成。在高频、大规模内部API中,这种差异可能转化为可观的带宽和CPU成本。

Q&A

HTTP/1.1 存在哪些主要性能问题?

HTTP/1.1 的主要性能问题包括:队头阻塞(一个连接上的请求必须按顺序处理,慢请求会阻塞后续请求)、每个请求都发送完整冗余的头部(如 Authorization 头可能数百字节)、不支持服务器主动推送(只能轮询或长轮询)、连接利用率低(浏览器通常打开多个并行连接,但每个连接都需要独立的 TCP 和 TLS 握手)。

HTTP/2 是如何解决 HTTP/1.1 的队头阻塞问题的?

HTTP/2 通过引入二进制分帧层和多路复用解决了 HTTP 层的队头阻塞。它在一个 TCP 连接上建立多个独立的流(stream),每个流可以并行传输请求和响应,互不阻塞。这样,一个慢请求不会阻塞其他请求的传输。

HTTP/3 相比 HTTP/2 有哪些关键改进?

HTTP/3 基于 QUIC 协议(使用 UDP),解决了 TCP 层的队头阻塞问题。QUIC 原生支持多路复用,一个流的数据包丢失不会影响其他流;内置 TLS 1.3 加密,减少握手往返次数;支持连接迁移(如从 WiFi 切换到蜂窝网络时连接不断开)。

REST 架构的六大约束是什么?

REST 的六大约束包括:客户端-服务器分离、无状态(每个请求包含所有信息)、可缓存(响应明确是否可缓存)、统一接口(资源通过 URI 标识,操作通过 HTTP 方法表达)、分层系统(客户端无需知道是否直接连接服务器)、以及可选的代码按需(服务器可发送可执行代码)。

REST API 存在哪些常见问题?

REST API 的常见问题包括:过度获取(返回固定字段,客户端可能只需要其中一部分)、获取不足(一个界面需要多个请求获取不同资源)、N+1 问题(获取列表后还需为每个项目额外请求)、不支持实时推送(需要轮询或长轮询)、以及文档漂移(文档与实际行为不一致)。

GraphQL 相比 REST 有哪些优势和劣势?

GraphQL 的优势:客户端可以精确指定所需字段,避免过度获取;一次请求可获取多个资源,解决 N+1 问题;强类型 schema 作为契约,支持构建时验证;前端可独立演进。劣势:查询复杂度可能过高,需要限制;缓存困难(通常使用 POST 请求,难以利用 HTTP 缓存);对于简单 CRUD API 可能过度设计;实时订阅扩展复杂;错误处理非标准(部分成功)。

WebSocket 和 HTTP 的主要区别是什么?

WebSocket 提供全双工、持久的通信,客户端和服务器可以随时互相发送消息,而 HTTP 是请求-响应模式,客户端必须发起请求。WebSocket 通过 HTTP 升级握手建立连接,之后消息开销小,适合实时应用如聊天、协作编辑和在线游戏。

Protocol Buffers 相比 JSON 有什么优势?

Protocol Buffers 是二进制格式,比 JSON 更紧凑,解析更快,因为字段名不需要传输,而是使用数字标签。它需要定义 .proto 文件作为 schema,提供强类型和向后兼容性。适合高性能、大规模内部 API,但不如 JSON 人类可读,需要额外工具链。

gRPC 为什么需要 HTTP/2?

gRPC 利用 HTTP/2 的多路复用和持久连接,可以在单个连接上并发处理多个 RPC 调用,并支持流式传输(客户端流、服务器流、双向流)。HTTP/2 的二进制帧和头部压缩也提高了效率。因此 gRPC 要求使用 HTTP/2 作为传输层。

如何根据需求选择通信方式(REST、GraphQL、WebSockets、gRPC)?

选择通信方式需考虑:如果 API 简单、需要广泛兼容和缓存,REST 合适;如果客户端需求多样、需要精确获取数据,GraphQL 合适;如果需要实时双向通信,WebSockets 合适;如果服务间需要高性能、强类型和流式调用,gRPC 合适。还需考虑团队熟悉度、生态和运维复杂度。

🏷️

标签

➡️

继续阅读