# 相关概念
# REST
- HTTP 协议定义了多种 HTTP 方法,优点是自由度较大,缺点是用法容易混乱。
- 例如,执行某个操作时,有的开发人员偏好使用 GET 方法,有的开发人员偏好使用 POST 方法。
- 因此,一些开发人员约束了 HTTP 协议的用法,制定了一套更简单的 API 规范,称为表述性状态转移(Representational State Transfer,REST)。
- 符合 REST 规范的 HTTP API 称为 RESTful API 。
- 主要规范:
- 调用 API 操作一个对象时,给该对象分配一个唯一的 URL 标识。
- URL 应该是名词性的,且区分单复数。比如
/students/names
优于/students/getName
。 - 尽量只使用 GET、POST、PUT、DELETE 四种 HTTP 方法,实现 CRUD 操作。
- 报文 body 通常采用 JSON 格式。
- 客户端与服务器之间采用无状态通信,所以客户端的每个请求都应该自带上下文信息。
- 优点:
- 简单易懂。
- 缺点:
- API 的操作对象,可能不适合用 URL 表示。
- 只使用几种基础的 HTTP 方法,不能体现某些特殊操作,比如既需要读、又需要写的操作。
# RPC
:远程过程调用(Remote Procedure Call),是一种进程间的网络通信技术。
- 用途:在本机某个进程的代码中,通过 RPC API ,调用其它主机上某个进程的代码。
- RPC 与 REST 的区别:
- REST 强调的是 API 的用法,必须遵守 REST 规范。而 RPC 强调的是 API 的用途,能实现远程过程调用。
- RESTful API 必须基于 HTTP 协议进行网络通信。而 RPC API 可以基于 TCP、UDP、HTTP 等通信协议。
- 例如 gRPC 是一个 RPC 分布式系统框架,基于 HTTP/2 协议,由 Google 公司发布。
# GraphQL
:一种查询语言,方便通过 API 查询图状数据。
- 2015 年,由 Facebook 公司发布。
- 用于 HTTP API 时,可视作 REST 的替代方案。
- 例:
- 客户端发出查询请求:
{ human(id: "2") { # 查询指定 id 的 human 对象,要求返回指定字段的值 name age } }
- 服务器返回响应:
{ "human": { "name": "Leo", "age": 20 } }
- 客户端发出查询请求:
# SSE
:全称为 Server-Sent Events ,是 2004 年发明的一项 HTTP 流式通信技术,主流浏览器都支持该功能。
- 工作流程:
- 客户端发送一个 HTTP 请求报文。
- 服务器返回一个 HTTP 响应报文,带有
content-type: text/event-stream
头部,表示 body 数据会分成多段传输。- 规定每段数据以
data:
开头,以\n\n
结尾。 - 双方保持当前 HTTP 通信所建立的 TCP 连接,直到传输了最后一段 body 数据。
- TCP 连接可能突然断掉。重新建立 TCP 连接时,需要知道 body 数据的传输进度。因此,建议每段数据包含
id: <int>
字段,取值递增。
- 规定每段数据以
- 例:用 Python 开发一个 HTTP 服务器,提供 SSE 接口
from flask import Flask, Response import time app = Flask(__name__) @app.route('/sse') def sse(): def iter_events(): for i in range(10): data = 'hello' yield f'data: {data}\nid: {i}\n\n' time.sleep(1) return Response(iter_events(), mimetype='text/event-stream') if __name__ == "__main__": app.run(debug=True)
# WebSocket
:HTML5 标准定义的一个网络通信协议。
- 属于应用层协议,基于 TCP 协议进行通信。
- 通信双方不能直接进行 WebSocket 通信,需要先通过 HTTP 通信进行握手,流程如下:
- 客户端发送一个 GET 请求,采用 HTTP/1.1 协议,请求头包含
Upgrade: websocket
和Connection: Upgrade
,表示请求从 HTTP 协议切换到 WebSocket 协议。 - 服务器如果同意切换,则返回一个响应报文,状态码为 101 (Switching Protocol) 。
- 双方保持当前 HTTP 通信所建立的 TCP 连接,开始 WebSocket 通信,可以收发多个 TCP 消息。
- 客户端发送一个 GET 请求,采用 HTTP/1.1 协议,请求头包含
- URL 分为两种格式:
- ws :格式为
ws://host:port/path
,通过 HTTP 协议进行握手,默认使用 TCP 80 端口。 - wss :格式为
wss://host:port/path
,通过 HTTPS 协议进行握手,默认使用 TCP 443 端口。
- ws :格式为
- 客户端的 JS 代码示例:
var ws = new WebSocket("ws://10.0.0.1/test"); ws.send("hello"); ws.send("world"); ws.close();
- 优点:
- 通用性强,大部分 HTTP 服务器,都支持切换到 WebSocket 协议。
- SSE、WebSocket 都允许服务器主动发送消息给客户端。与之相比,HTTP 通信时,服务器遇到紧急消息,不能立即通知客户端,只能等客户端下一次发送 HTTP 请求报文。
- SSE 只允许服务器发送多条消息,而客户端只能发送一条消息。而 WebSocket 支持全双工通信。
- SSE 只支持发送 text 格式的数据。而 WebSocket 支持发送任意格式的数据。
- 缺点:
- 需要维持 TCP 长连接,会增加服务器的负载。
- 如果网络不稳定,则 TCP 连接会经常断掉,需要重新 WebSocket 握手。