速成课 · No. 05
两个程序只有在就规则达成一致时才能协作——发送什么、以什么形状发送、谁在什么时候说话。协议就是这份约定,而挑对协议,就是在选择这场对话怎么进行。
21 个概念 · 每个都有一张图 · 结尾附速查表
协议是两个程序用来对话的、约定好的一套规则——一条消息长什么样,以及谁可以在什么时候说什么。把规则定对,千差万别的系统就能彼此听懂。
Protocol——一门语言加一套礼仪
两位没有共同母语的外交官仍能谈判——因为他们事先就一门语言、以及发言的顺序达成了一致。任意一边一破,剩下的就只是噪声。
协议定下两样东西:消息的格式(好让两边都能读懂它),以及编排(谁先开口,回复何时到来,怎么结束)。HTTP、gRPC、WebSocket——每一个不过是关于这两件事的一份不同约定。同样的活儿,不同的举止。
- 是什么
- 两个程序之间的合同:消息的形状 + 对话的顺序。
- 例子
HTTP:客户端发送
GET /users/42,服务器用200 OK加 JSON 作答。没有人抢话。- 坑
- 如果双方对合同的理解不同,你得到的是噪声,而不是一个错误。
- 关联
- 这门课里的其他每个概念,都是一种具体的协议或格式。
Protocol stack——协议是分层的
一封信:邮政系统负责搬运信封,根本不在乎里头是什么;纸上的语言则是你和读信人之间的事。两份独立的约定,叠在一起。
底下是一个传输协议——TCP 或 UDP——它只负责在机器之间搬运字节。上面是一个应用协议——HTTP、gRPC、MQTT——它赋予那些字节以含义。两者之间通常还有 TLS,把信封封起来。你通常工作在最上层——但当事情变慢、变得不稳定时,底层就会渗上来。
- 是什么
- 协议一层叠一层:传输层搬运字节,应用层赋予它们含义。
- 例子
- HTTP 跑在 TLS 上,TLS 跑在 TCP 上,TCP 跑在 IP 上。
- 坑
- 变慢和掉线往往来自下层——盯着 HTTP 看是修不好的。
- 关联
- 底下是 TCP / UDP,上面是 HTTP、gRPC、MQTT,中间是 TLS。
每个协议都要回答三个问题
一场对话需要先定下三件事:谁先开口,用什么语言,是轮流说还是双方同时说。
谁发起——是客户端来问,还是服务器也能主动推送?数据长什么样——JSON 文本、紧凑的二进制,还是连续的流?时机——一锤子买卖,还是一条长期保持的线路、双方随时都能开口?协议之间几乎所有的差别,都是对这三个问题的不同回答。
地图:五组共 21 个概念
一张地铁图:先看清整条线路,再一站一站地坐下去。
这门课里的每个概念都属于五组之一:地基(一切所依托的东西)、请求–响应(问一句,得一个答案)、实时(服务器先开口)、消息(双方之间有个中间人)和格式(里面数据的形状)。
怎么读每个概念
一本护照:每个人的栏目都一样,所以很容易比较。
下面的每个协议都按同一套方式讲:它的英文名称(你查文档时要搜的词)、一幅现实生活里的画面、一张图,以及一张带字段的卡片:是什么、怎么运作、例子、代价(你要付出什么)、何时使用和关联。最重要的一条规则:**没有最好的协议,只有合适的协议。**你不会用对讲机发婚礼请柬,也不会靠寄信来协调一场救援。
协议是一份约定。按对话的形状去选它,而不是按什么流行。
你构建的几乎每样东西底下,都坐着几个你很少直接碰、却始终依赖的协议。了解它们——它们决定了上层到底能做什么。
TCP——保证送达的可靠线路
一通电话,对方每说完一句都回你一声“收到”——慢一点,但什么都不会丢、不会乱。
TCP(Transmission Control Protocol)先建立一条连接——也就是握手(handshake)。然后它保证每个字节都按顺序到达:接收方确认自己收到了什么,丢掉的就重发。它是网页、电子邮件和大多数 API 底下干活的主力。
- 是什么
- 一种带保证的传输:全部送达,按顺序,不丢。
- 怎么运作
- 握手、确认(ACK)、重发丢失的部分。
- 例子
- HTTP/1.1 和 HTTP/2、电子邮件、数据库、大多数 API 的底层。
- 代价
- 建立连接和等待重发会带来一点延迟。通常是笔很划算的交易。
- 何时使用
- 每个字节都重要的时候——几乎总是如此。
- 关联
- 反面是 UDP。上面跑着 HTTP、TLS、消息中间件。
UDP——发出去就不管,又快又会丢
隔着一间嘈杂的屋子喊话——快,但漏听了一个词你也不会停下来重复,继续往下说就是了。
**UDP(User Datagram Protocol)**发送数据包,没有握手,也不保证送达和顺序。这听起来很糟,直到你想要的是速度而不是完美:视频通话、实时游戏、DNS 查询。在这些场景里,丢一帧画面,好过为了等重发而卡顿。
- 是什么
- 一种没有任何保证的传输:发出去就不管。
- 怎么运作
- 没有连接、没有确认、没有重发、没有顺序。
- 例子
- 视频通话:旧的一帧没有用——不如直接显示下一帧。
- 代价
- 丢包和乱序要你自己处理(或者容忍)。
- 何时使用
- 新鲜比完整更重要的时候:语音、视频、游戏、DNS。
- 关联
- QUIC 建立在它之上,HTTP/3 又建立在 QUIC 之上。
HTTP——网络世界的请求–响应语言
商店柜台:你要一样东西,得到一个回答,你一转身店员就忘了你。
HTTP(HyperText Transfer Protocol)跑在 TCP 之上,定义了大家熟悉的请求/响应:方法 GET、POST、PUT、DELETE 和状态码 200、404、500。它是无状态的——每个请求都独立成立——而这恰恰让网络得以扩展到数十亿次调用。
- 是什么
- “问一句,得一个答案”的应用层协议。
- 怎么运作
- 请求 = 方法 + 路径 + 请求头 + 正文。响应 = 状态码 + 响应头 + 正文。
- 例子
GET /users/42→200 OK,正文是 JSON 格式的用户。- 代价
- 服务器不能先开口——只能回答。
- 何时使用
- 你会碰到的几乎每个 API 都说它。
- 关联
REST、GraphQL、SSE、Webhook 的基础;WebSocket 从它起步。
TLS 与 HTTPS——同样的东西,但封好了
同一封信,这回装进了防拆封的信封,外面还有寄信人经过验证的签名。
TLS(Transport Layer Security)给 HTTP(以及其他协议)包上加密和身份验证:中间的任何人都读不到、也伪造不了流量,而证书证明服务器确实是它所声称的那一个。它就是 HTTPS 里的那个“S”——而且早已不再是可选项:浏览器、应用商店和 API 都默认它存在。
- 是什么
- 叠在传输层之上的加密与身份验证层。
- 怎么运作
- 由证书为服务器担保;之后所有流量都被加密。
- 例子
- 浏览器地址栏里的小挂锁就是 TLS。
- 代价
- 证书需要签发和续期(如今几乎免费)。
- 何时使用
- 只要数据离开了你的机器,就该放在 TLS 里。
- 关联
- 包裹着 HTTP、gRPC、WebSocket、消息中间件。
HTTP/2 与 HTTP/3——同一根管道,变宽了
一条单车道的路变成了多车道的高速公路——然后又被重建,让一辆抛锚的车不再堵住所有车道。
HTTP/1.1 在每条连接上一次只处理一个请求。HTTP/2 在一条连接上同时跑很多个——这就是多路复用(multiplexing)。但它建立在 TCP 之上,所以丢一个包就会卡住所有的流——这就是队头阻塞(head-of-line blocking)。HTTP/3 改用 QUIC(跑在 UDP 上):丢包只会卡住它自己那条流,建立连接大约只要一次往返,手机还能在 Wi-Fi 和蜂窝网络之间切换而不断线。
- 是什么
- HTTP 的新版本:同样的请求,底下是一条更快的路。
- 怎么运作
HTTP/2——一条 TCP 连接里有多条流。HTTP/3——跑在 UDP 之上的 QUIC 里,各条流彼此独立。
- 例子
- 一个有上百张图片的页面,通过一条连接并行加载它们。
- 代价
- 对你几乎没有——在服务器或 CDN 那里打开开关就行。
- 何时使用
- 默认就用,只要环境支持。你的应用代码不用改。
- 关联
- gRPC 跑在 HTTP/2 上;HTTP/3 跑在 UDP 上。
你构建在栈的顶层,但决定能做什么的是底层。而加密不是以后再补上的一层。
应用与服务器之间、服务与服务之间的大部分对话,都是“问一个问题,得一个答案”。三种风格占主导,它们以不同的方式用简单换取能力。外加一位你仍会碰到的老前辈。
REST——建立在朴素 HTTP 动词之上的资源
一座井井有条的图书馆,每本书都有固定的位置,而你在哪儿都用同样的四个动作:看、加、改、删。
REST(Representational State Transfer)把一切建模成位于 /users/42 这类 URL 上的资源,用 HTTP 动词来操作,通常返回 JSON。它简单、可缓存、能在浏览器里调试,到处都有人懂——是公开 API 的默认选择。
- 是什么
- 一种 API 风格:URL 上的资源 + HTTP 动词 + 通常是 JSON。
- 例子
GET /users/42读取它,DELETE /users/42删除它。- 代价
你常常拿到的数据比需要的多(over-fetching,过度获取),或者为填满一个页面要调用好几次(under-fetching,获取不足)。
- 何时使用
- 面向很多客户端的公开 API。几乎总是起点。
- 关联
- 跑在 HTTP 上,说 JSON。GraphQL 补上了它的弱点。
GraphQL——只要你想要的那些字段
一家自助餐厅:不是固定套餐,而是你递给后厨一份精确的清单,端回来的恰好就是这些——不多也不少。
GraphQL 提供一个端点,由客户端写一条查询,一次往返就取回它所需的确切字段——终结了 REST 的过度获取和获取不足。当很多不同的客户端(网页、移动端、合作伙伴)需要一张复杂数据图谱的不同切片时,它非常出色。
- 是什么
- 一个端点;由客户端描述答案的形状。
- 例子
- 移动端的一个页面需要名字和订单总额——它就只要这两样。
- 代价
- 缓存更难做,而且这份灵活性把真正的复杂度压到了你的服务器上。
- 何时使用
- 客户端五花八门,数据图谱又复杂、关系紧密。
- 关联
- 对 REST 弱点的一个回答;通常跑在 HTTP 上,配 JSON。
gRPC——像调用本地函数一样调用远程函数
同一栋楼里两个房间之间的对讲机——简短、快速、私密,因为双方早已共用同一套简语。
gRPC 是一个 RPC(Remote Procedure Call,远程过程调用)框架——通过网络调用一个函数。它在 HTTP/2 上使用 Protocol Buffers(紧凑的二进制),让一个服务能直接调用另一个服务的方法,自带强类型合同和流式传输。又快又严格——非常适合内部的服务间流量。
- 是什么
- 按一份严格的合同,通过网络调用另一个服务的函数。
- 例子
- 订单服务对仓库服务调用
inventory.Reserve(item, 2)。 - 代价
- 原生不适合浏览器;二进制负载人眼读不懂,所以调试要靠工具,而不是靠眼睛。
- 何时使用
- 你自己的服务之间频繁、快速地互相通信。
- 关联
- 跑在 HTTP/2 上,说 Protobuf。
SOAP——老前辈
一份一式三份、盖了章、经过公证的正式合同——笨重,但毫不含糊。
在 REST 之前,**SOAP(Simple Object Access Protocol)**把调用包在严格的 XML 信封里,并配有正式的 WSDL 合同。它啰嗦、老派,但它的严谨至今仍活在银行、支付和企业集成之中。
- 是什么
- 一种带正式合同的严格 XML 调用协议。
- 例子
- 银行集成:在
soap:Envelope里装一个GetBalance。 - 代价
- 啰嗦、笨重,现代工具很少。
- 何时使用
- 你大概不会新建一个——但很可能得和一个打交道。
- 关联
- 说 XML;在新系统里它的位置被 REST 和 gRPC 取代了。
REST,为了让所有人都看得懂。GraphQL,为了让客户端自己选。gRPC,为了在你自己的服务之间跑得快。
朴素的请求/响应有个缺口:服务器不能先开口。当客户端需要在事情发生的当下就听到消息时,你就会用到下面这些。
Polling——不停地问“有新消息吗?”
一个孩子在长途自驾的路上,每隔两分钟就问一句“到了没?”。简单——而且多半是白费口舌。
**Polling(轮询)**是最粗糙的办法:客户端按定时器反复发请求。**Long-polling(长轮询)**对它做了改进:服务器把每个请求一直挂着,直到真有话要说,然后客户端立刻再问一次。它到处都能用,不需要任何特殊协议。
- 是什么
- 客户端一遍又一遍地向服务器询问有没有新消息。
- 例子
- 订单状态页每隔 10 秒问一次服务器。
- 代价
- 和真正的流相比,既浪费又滞后。
- 何时使用
- 做备用方案不错,做默认方案很差。
- 关联
- 真正的替代品是 SSE 和 WebSocket。
SSE——来自服务器的单向流
一档电台广播——电台持续向你播送;你只管听,不会在同一个频道上回话。
SSE(Server-Sent Events)让一个 HTTP 响应一直开着,由服务器向客户端推送一串更新,自带自动重连,开销几乎为零。非常适合单向的数据流:实时比分、通知、跳动的仪表盘——LLM 把 token 流式推送到聊天界面用的也是它。
- 是什么
- 在普通 HTTP 上,从服务器到浏览器的单向事件流。
- 例子
- 聊天机器人的回答在模型写作的同时一个词一个词地冒出来。
- 代价
- 只有一个方向;客户端的回复要作为单独的请求发出。
- 何时使用
- 如果客户端不需要在同一条线路上回复,SSE 是最简单的实时工具。
- 关联
- 跑在 HTTP 上;它的双向兄弟是 WebSocket。
WebSocket——双向都开着的线路
一条没挂断的电话线——任何一方一有话就能立刻说,不用重拨。
WebSocket 把一条 HTTP 连接升级(upgrade)成一条持久的全双工通道,客户端和服务器可以自由地互发消息,延迟最低,每条消息的开销极小。当双方都在不停说话时,它就是对的工具:聊天、多人游戏、协同编辑、实时交易。
- 是什么
- 一条持久的通道,双方随时都能开口。
- 例子
- 聊天:“正在输入……”、新消息和队友的光标,双向飞来飞去。
- 代价
- 运维起来比 SSE 麻烦:长连接、重连、负载均衡。
- 何时使用
- 当你确实需要双向的时候。
- 关联
- 从 HTTP 起步;单向的替代品是 SSE。
Webhook——别打给我们,我们打给你
把你的电话号码留给店家,订单到了他们打给你——而不是你每个钟头就跑回去看一趟。
Webhook 把方向反了过来:**你登记一个 URL,事件发生时,对方服务就向它发一个 HTTP 请求。**这是服务之间互相通知的标准做法,没有谁需要坐在轮询循环里干等。
- 是什么
- 对方服务那边一有事情发生,就给你发一个 HTTP 请求。
- 例子
支付一成功,Stripe 就向你的端点
POST;每次 push,GitHub 都会通知你的服务器。- 代价
- 你的端点必须能从外部访问,并且要扛得住重试和失败。
- 何时使用
- 一个服务告诉另一个服务:“有事件发生了。”
- 关联
- 就是普通的 HTTP,只是方向反过来;取代了 Polling。
如果服务器必须先开口,就别再轮询了。单向流用 SSE,双向用 WebSocket。
有时候 A 根本不该直接调用 B。在两者之间放一个 broker,发送方就可以发完即走,而接收方按自己的节奏干活。
Message broker——替你保管消息的中间人
夹在寄信人和收信人之间的邮局——你把信放下就走;对方准备好了再来取。双方不必同时在场。
不再是直接调用,而是由生产者把消息交给一个 message broker,由它投递给一个或多个消费者。这让两者在时间上解耦(接收方可以慢,也可以短暂宕机),也在认知上解耦(发送方不必知道谁在听)。它是那些有韧性、负载起伏大的异步系统的脊梁。
- 是什么
- 一个接收、保存并分发消息的中间人。
- 例子
- Web 服务器放下一条“订单已创建”;仓库和邮件服务各自来取。
- 代价
- 多一个要运维的系统;不再有“马上回答我”这回事了。
- 何时使用
- 慢活儿、流量尖峰、很多接收方。
- 关联
- 它的几种形态是队列(AMQP)、日志(Kafka)、发布/订阅(MQTT)。
Message queue(AMQP / RabbitMQ)——一份活,一个 worker
饭馆里订单暴增——小票在挂架上堆起来,哪位厨师有空就取下一张。
Message queue(消息队列)保存任务,直到某个 worker 取走一个、处理它,并确认(ack)。像 AMQP(RabbitMQ 说的就是它)这样的协议又增加了智能路由、重试和投递保证。
- 是什么
- 任务排着队等;每个任务恰好被一个 worker 取走。
- 例子
把“发送欢迎邮件”或“生成发票”丢进队列,这样 Web 请求立刻返回,而慢的那部分由 worker 去处理。
- 代价
- 处理完的任务就没了——你没法回头重读历史。
- 何时使用
- 不该拖慢用户的后台工作。
- 关联
- broker 的一种形态;如果有很多读者、还需要历史——用 Kafka。
Kafka——很多人都能回放的持久日志
一座报纸档案馆——每一期都按顺序保存着,任意数量的读者都可以从任何位置开始,按自己的速度往后读。
Kafka 与其说是队列,不如说是一份持久、有序的事件日志:许多消费者各自独立地读它,读完之后它依然留在那里。每个读者都记着自己的位置——它的 offset。它为极高的吞吐量而生。
- 是什么
- 一本事件日志,被保留下来,由许多人各自独立地读取。
- 例子
- 同一条“订单已下”的事件流,同时喂给数据分析、搜索索引和邮件。
- 代价
- 系统很重;每天只有几百条消息的话就是杀鸡用牛刀。
- 何时使用
- 事件量巨大,而且有很多读者需要历史记录。
- 关联
- 队列:消息一经处理就没了。Kafka:历史会留下来。
MQTT——为不可靠网络而生的迷你发布/订阅
一支送货车队用的对讲机频道——短促的通话、低功耗,有一辆暂时开进隧道也没关系。
MQTT 是一种超轻量的发布/订阅(pub/sub)协议,为 IoT 而造:设备把消息发布到主题(topic)上,由 broker 把它们交给订阅者。消息极小,电量和带宽的消耗极低,还能容忍不稳定的链路。
- 是什么
- 一种轻量的发布/订阅协议,给弱设备、弱网络用。
- 例子
- 成千上万的传感器、智能家居设备或车辆,通过蜂窝网络上报遥测数据。
- 代价
- 需要一个 broker;用在普通的 Web 上是错误的工具。
- 何时使用
当“客户端”是弱网络里的一颗廉价芯片时,MQTT 适用于 HTTP 不适用的地方。
- 关联
- broker 的一种形态;它的传输层是 TCP。
别让调用方为慢活儿干等。把它交给 broker,然后继续往前走。
协议是信封;里面的内容仍然需要一个双方都认可的形状。这个选择是在可读性与速度之间悄悄做的一笔权衡。
JSON——可读、通用、默认之选
一张谁都能一眼看懂的手写便条——稍微长了点,但不需要解码器。
**JSON(JavaScript Object Notation)**是文本,人能读,到处都支持——是 Web 和 REST API 默认的正文格式。你可以在浏览器里直接扫一眼,靠阅读来调试。下面是同一条记录的三种格式:大小的差别一目了然。
- 是什么
- 一种键–值的文本格式,人和机器都能读。
- 例子
{"id": 42, "name": "Ann"}- 代价
啰嗦,解析也不是最快的——通常没问题,偶尔在大规模下会成为瓶颈。
- 何时使用
- Web 和公开 API 默认就用它。
- 关联
- REST 和 GraphQL 的语言;二进制的替代品是 Protobuf。
Protocol Buffers 及其同类——小、快、二进制
一枚条形码——你看不懂,但一扫就识别,而且排得很紧凑。要解码它,你得有那份模式(schema)。
像 Protocol Buffers(Protobuf)——gRPC 用的就是它——以及 MessagePack 和 Avro 这样的二进制格式,依据一份共享的模式(schema)把数据序列化成紧凑、快速的负载。好处是体积和速度;代价是肉眼读不了,而且双方必须共享这份模式。
- 是什么
- 一种紧凑的二进制格式,事先由一份模式来定义。
- 例子
message User { int32 id = 1; string name = 2; }→ 线路上只有 7 个字节。- 代价
- 肉眼读不了;双方必须保持模式同步。
- 何时使用
- 大流量、内部的、对性能要求苛刻的通信。
- 关联
- gRPC 的语言;可读的替代品是 JSON。
XML——啰嗦、正式、仍然健在
一份法律文件——标签和结构堆得满满当当,精确无比,但写张便条时谁都不会第一个想到它。
XML(eXtensible Markup Language)比 JSON 更早出现,带有丰富的模式与校验,代价是体积臃肿——每个值都夹在一个起始标签和一个结束标签之间。你会在 SOAP 服务、文档格式和配置文件里碰到它。
- 是什么
- 一种基于标签、带严格模式的文本格式。
- 例子
`
42 Ann `
- 代价
- 臃肿:同一条记录几乎是 JSON 的两倍长。
- 何时使用
- 新东西很少用——但它仍然撑着不少老系统。
- 关联
- SOAP 的语言;在 Web 上被 JSON 取代了。
文本是为了让人看懂,二进制是为了快。大多数 API 默认用可读的格式,是对的。
你不是给一个系统选一个协议——而是给每一场对话选对的那个。真实的应用同时会跑好几种。
让协议匹配这场对话
一个工具箱,里面有锤子、螺丝刀、扳手。你不会争论哪个最好——你只看眼前的活儿。
按对话的形状来决定。问题从来不是“选哪个协议”,而是“这一条线路,选哪个”。
从简单开始;疼了再去碰那些花哨的
你不会为了把一袋面粉运过院子,专门去铺一条铁路。
大多数产品靠 HTTPS 上的 REST + JSON,再加一个跑后台任务的队列,就能走得很远。gRPC、GraphQL、Kafka 和 WebSocket 是针对具体痛点的答案——服务间延迟、“贪心”的客户端、巨大的事件量、实时交互。等你真切感到那种痛再采用它们,而不是因为听起来时髦。最简单、又能匹配这场对话的协议,通常会赢。
这一切如何连在一起
一块千层蛋糕:每一层都压在下面那层上,而从上往下你只看得到糖霜。
格式装在 API 风格里面,风格跑在 HTTP 或消息中间件之上,这一切都包在 TLS 里,最底下是 TCP 或 UDP。一个真实的应用,轻易就会同时用到这幅图的一半。
- 谁来发起对话——客户端,还是服务器?
- 消息多久一条、有多大?
- 一对一,还是随时间推移一对多?
- 需要可读吗,还是越小越快越好?
- 客户端是谁——浏览器、移动应用、我自己的另一个服务,还是一个小设备?
- 在去碰更花哨的东西之前,普通的 REST + JSON 够用吗?
- 你为一个必须让浏览器来调用的公开 API 选了 gRPC。
- 明明一个刷新按钮就够了,却用了 WebSocket。
- 用 Kafka 来搬每天几百条消息。
- 为一个每次都只取那三个字段的客户端用了 GraphQL。
- 对你需要经常用手去读、去调试的数据,用了二进制格式。
- 客户端和服务器彼此一致,不需要胶水代码在两者之间翻译。
- 协议匹配流量——流用流式,问题用请求/响应。
- 你可以用协议所期望的工具来调试它——浏览器、日志,或 proto 工具。
- 加密默认开着,处处如此。
- 每场对话都用最简单、能匹配它的协议,不多不少。
速查表:全部 21 个概念
基础
- Protocol约定
两个程序之间的合同:消息的形状 + 对话的顺序。
- Protocol stack分层
分层:传输层搬运字节,应用协议赋予它们含义。
地基
- TCP传输控制协议
可靠、按顺序的送达:握手、确认、重发。
- UDP用户数据报协议
发出去就不管:快但会丢。视频、游戏、DNS。
- HTTP超文本传输协议
无状态的请求–响应:方法和状态码。
- TLS / HTTPS传输层安全
加密 + 服务器身份。HTTPS = 装在 TLS 里的 HTTP。
- HTTP/2 · HTTP/3多路复用、QUIC
一条连接上跑很多请求;HTTP/3 跑在 UDP 之上的 QUIC 上。
请求与响应
- REST表述性状态转移
URL 上的资源 + HTTP 动词 + JSON。公开 API 的默认之选。
- GraphQLAPI 的查询语言
一个端点;客户端只要它需要的那些字段。
- gRPC远程过程调用
调用另一个服务的函数:HTTP/2 + Protobuf,严格的合同。
- SOAP简单对象访问协议
严格的 XML 信封和 WSDL。在银行和企业里继续活着。
实时与推送
- Polling长轮询
客户端不停地问“有新消息吗?”。一个备用方案。
- SSE服务器发送事件
通过一个 HTTP 响应,从服务器到客户端的流。LLM 的 token 流式输出。
- WebSocket全双工通道
一条打开的线路,双方随时开口。聊天、游戏。
- WebhookHTTP 回调
事件发生时,一个服务向你的 URL 发 POST。
消息
- Message broker中间人
让发送方和接收方在时间上、在认知上解耦。
- Message queueAMQP、RabbitMQ
任务排队等候;恰好有一个 worker 取走它。
- Kafka事件日志
持久的日志:很多读者,各有各的位置,历史会保留。
- MQTT面向 IoT 的发布/订阅
通过主题传递轻量消息,给弱设备和弱网络用。
格式
- JSONJavaScript 对象表示法
可读的文本,Web 的默认之选。略显啰嗦。
- ProtobufProtocol Buffers
按模式生成的紧凑二进制。快,但肉眼读不了。
- XML可扩展标记语言
标签加严格的模式。臃肿;活在老系统和 SOAP 里。
现代应用不是建立在某一个协议之上的。它们建立在为每场对话选对的协议之上——而且处处裹着 TLS。