RESTFUL API

虽然HTTP协议已经规范了基础的请求/响应格式,但正是因为它太灵活,反而导致了早期Web服务的混乱。

HTTP原生问题: 同一个用户查询功能,不同开发者可能设计出完全不同的接口

所以导致了 RESTFUL API的诞生!

约定:

URL 表示资源,如 /users/1

用标准 HTTP 动词:GET 查,POST 新增,PUT 修改,DELETE 删

数据统一用 JSON(或标准格式)

服务无状态(每次请求都完整表达意图)

规范为


HTTP/1.1 201 Created
Location: /users/123
Content-Type: application/json

{ "id": 123, "name": "Alice" }


// 传统混乱的响应
{
  "success": true,
  "code": 200,
  "message": "OK",
  "data": { "id": 123, "name": "Alice" }
}

也就是说:

HTTP 可以发任何东西,RESTful API 让它发得标准、发得规范。

注意:

RESTful API 规范是靠人遵守的工程文化,不是自动生效的。

gRPC

基于 HTTP/2协议 一个高性能 RPC 框架,使用_Protocol Buffers(protobuf)_作为接口定义语言(IDL)和数据序列化工具。

HTTP/2

因为HTTP/1.1出现了问题_队头阻塞_

虽然HTTP/1.1支持长连接,复用TCP连接,处理多个请求,但是: 同一时刻只能处理一个请求,等响应回来才能发下一个(串行处理)


HTTP/2 使用 二进制帧。

将请求/响应拆分为更小的 帧(Frame)

一个 TCP 连接可_并行_传输多个请求/响应,避免队头阻塞。

主动推送

服务器可以预测客户端需要的资源,在响应主请求时一并发送,服务器可以 主动推送资源(如 CSS、JS)给客户端,无需等待请求。

推送承诺(PUSH_PROMISE):先告知客户端将要推送哪些资源

缓存消化:客户端可以拒绝已缓存的推送

客户端可以指定流的优先级(如优先加载 HTML,再加载图片)。

每个帧带有 流 ID(Stream ID),客户端和服务器可以_乱序发送和重组数据_。

二进制帧

把一个完整的消息拆分为多个标准的帧,帧的内容可能包括

  1. HEADERS帧 - 包含HTTP头信息

  2. DATA帧 - 包含消息体(如HTML内容)

  3. SETTINGS帧 - 连接配置参数

  4. PRIORITY帧 - 流优先级

  5. PUSH_PROMISE帧 - 服务器推送预告

每个帧都有固定的9字节头部:

+-----------------------------------------------+ | Length (24 bits) | 帧负载长度 | Type (8 bits) | 帧类型 | Flags (8 bits) | 标志位 | R (1 bit) | Stream Identifier (31 bits) | 流ID +-----------------------------------------------+ | Frame Payload (0~16,777,215 bytes) | 帧内容 +-----------------------------------------------+

流思想

一个流代表一个完整的请求-响应交换,

每个流有唯一的ID标识

一个TCP连接可以同时承载多个流

####HTTP/2 如何并行

物理层:只有一条TCP连接

逻辑层:通过流ID(Stream ID)创建多个虚拟通道

工作方式:不同流的帧可以交替发送,接收方根据流ID重组

在有序的TCP字节流之上构建无序的帧传输

通过流ID实现逻辑分离

请求流程

假设浏览器请求一个网页和其关联的CSS文件:

客户端发起流1(HTML请求):

发送HEADERS帧(包含GET /index.html)

服务器响应流1:

发送HEADERS帧(HTTP 200 OK)

发送多个DATA帧(HTML内容分块)

服务器主动推送CSS(流2):

发送PUSH_PROMISE帧(预告将推送/style.css)

发送HEADERS帧(HTTP 200 OK)

发送DATA帧(CSS内容)

所有这些帧在同一个TCP连接上交错传输

HPACK 压缩算法

用索引代替重复的字符串,减少传输量

传统HTTP1.x的头部问题:


GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml
Accept-Language: zh-CN,zh;q=0.9
Cookie: session_id=abc123; theme=dark

重复传输:每次请求都发送几乎相同的头部字段

纯文本格式:占用空间大且不易压缩

增长趋势:现代网页平均请求头已达1.5KB+

静态表编码:

:method: GET → 只需发送0x82(二进制10000010)

动态表编码:

哈夫曼编码:

如何利用HTTP2

  1. 多个 gRPC 调用可以在同一个 TCP 连接上并行传输,避免 HTTP/1.1 的队头阻塞。
  2. Protocol Buffers(protobuf)本身就是二进制格式,与 HTTP/2 的二进制帧天然契合。
  3. HTTP/2 的流式特性使得 gRPC 的 Server Streaming、Client Streaming 和 Bidirectional Streaming 成为可能。
  4. 头部压缩(HPACK)减少了 gRPC 调用的元数据开销。

Protocol Buffers

IDL 与编程语言无关的类型系统,用于明确定义服务接口。IDL定义了:

  1. 服务提供哪些功能(方法)

  2. 每个方法的输入输出结构

  3. 数据类型和字段约束

数据序列化:

将内存中的对象转换为可以存储或传输的二进制/文本格式的过程

// Go结构体
user := User{
    ID:   "123",
    Name: "Alice",
    Age:  30,
}

// 序列化为protobuf二进制格式
data, _ := proto.Marshal(&user)
// 得到紧凑的二进制:0x0a036132... (实际二进制数据)

WebSocket

消息队列