摘要

  • 服务器在 EHLO 中声明 PIPELINING 后,客户端可以不逐条等待便发送一组命令;节省的是往返时间,不是把多项决定合并成一项。
  • 这条快车道依赖逐条计数、按状态划定批次、识别多行回复、服从 TCP 流量控制,以及服务器绝不丢弃已经读到的输入。

昂贵的是空白时间

普通 SMTP 像一次谨慎的问答:自报身份,等;给出发件人,等;提交收件人,等;请求进入数据阶段,再等。RFC 2920 指出,高时延链路会显著放大这种一问一答,甚至让等待回复的往返时间主宰整条连接。

流水线允许几条已知命令先后发出,再统一接收各自的判断。服务器仍然分别处理每一条,性能来自同时存在多项待决意图。

这也改变了责任。在锁步模式下,下一份回复几乎只可能属于唯一未决命令;流水线里有多位候选者,客户端必须保存一份不会错位的账。

不能用理论替代能力声明

TCP 保证字节有序,却不能保证每台 SMTP 实现都能安全处理提前到达的命令。RFC 2920 记录了真实部署中的三类缺陷:进程交接可能丢掉已经预读到私有缓冲区的字节;一条命令失败后,服务器可能错误地清空 TCP 输入;服务器还可能把最后一个 RCPT TO 的结果当成全部收件人的状态,从而误判 DATA。

因此,客户端必须先发送 EHLO。只有收到 250 且回复列出 PIPELINING,才能选择流水线。IANA SMTP 服务扩展注册表 至今仍将该关键字登记到 RFC 2920,且没有参数。

它没有公布批次大小、处理速度或投递承诺。服务器只声明自己能守住一项行为不变量;客户端仍可决定不用、少用或逐步扩大批次。

会改变状态的命令负责收尾

RFC 2920 允许 RSET、发件人命令与 RCPT TO 出现在组内,却要求 EHLO、DATA、VRFY、EXPN、TURN、QUIT 和 NOOP 等命令只能位于组尾。因为它们的成败会改变客户端必须面对的状态,后续动作不能假装结果已经知道。

这个边界区分并行与依赖。多个收件人可以分别等待裁决;是否进入数据阶段却必须先听到回答。NOOP 的业务含义很轻,因而恰好可以充当同步点。后来的扩展可以另行规定自己的边界,没有规定就不等于授权任意插入。

回复的所有权由位置决定

设想客户端连续发出一位发件人、三位收件人与 DATA,便有五份回复待认领。多个回复可以使用同一状态码,文字也会因实现而异。RFC 2920 明确禁止靠错误码或说明文字配对。

客户端必须按已发命令的数量,逐份计算独立回复的位置,而且每份都要检查。即使所有收件人都失败,也不能推定 DATA 一定被拒绝。若服务器反常地接受,客户端应只发送终止用的单独句点,让对方结束错误状态,而不是发送一封无人可收的邮件。

多行回复更容易造成错账。中间行在状态码后带连字符,最后一行没有。把每行都算成一份回复,会使余下所有判断整体错位。语义只能解释已经归属的结果,不能反过来猜结果归谁。

TCP 有序不等于双方会前进

非阻塞客户端可以在上一次发送仍有字节待出时读取回复。阻塞客户端若做不到,就必须确认整个命令组能装进当前 TCP 窗口。否则客户端等待写完,服务器等待客户端读取已经返回的数据,两边都没有违反各自的局部顺序,却可能永久相等。

RFC 2920 当年提到窗口通常但并非总是 4K 八位组。这是历史观察,不是现代通用参数。持久规则是:要么让批次服从真实流控,要么并发读写。

流水线增加了尚未确认的意图总量。吞吐来自并发,活性来自可证明的上限。

服务器承诺不抹去输入

声明 PIPELINING 的服务器必须按照命令到达次序回复,不得假定尚未收到的命令,并在本地 TCP 输入缓冲区清空时立即发出积压回复。最强的一条要求是:任何情况下都不得清空或丢失 TCP 输入内容。

一次收件人拒绝不能授权删除后面已经抵达的命令;进程切换也不能让预读字节失去证据地位。缓冲区承载的是客户端已经表达的意图,而不是实现可以随手丢弃的草稿。

服务器可以合并部分普通回复以提高效率,却不能缓冲组尾命令或未知命令的回复。它可以少发几次包,但不能隐去客户端必须转向的时刻。

三份 RFC 保留同一条机制

RFC 1854 在 1995 年首次规定扩展。RFC 2197 于 1997 年取代它,并明确只有文字与编辑变更,协议没有改变。2000 年,RFC 2920 取代 RFC 2197,成为 STD 60。RFC 5321 后来仍把 SMTP 描述为刻意锁步的一次一条,同时承认 RFC 2920 这类双方同意的扩展可以改变节奏。

关键字不认证对端,不接受发件人或收件人,不预留存储,不保证投递,也不证明下一跳支持同样能力。它只在本次会话中开放一种严格受限的并发。

历史价值正在这种克制里:只有运行中的双方都能保存必要证据时,往返等待才可以被安全地省去。

来源与限制

规范沿革见 RFC 1854、RFC 2197 与 RFC 2920;SMTP 基线来自 RFC 5321,当前登记来自 IANA。这些材料不提供今天的部署比例、厂商默认值、性能幅度或故障率。