RFC 10:Documentation Conventions——当技术讨论开始扩容,RFC 如何成为一套可运行的协作协议
RFC 10 没有定义一个网络报文,却解决了另一个同样真实的系统问题:当参与 ARPANET 协议设计的人和站点迅速增加时,技术意见怎样被唯一编号、稳定引用、可靠分发,又怎样避免“写成文档就自动变成权威结论”。它对 RFC 3 的修订幅度并不大,恰恰因此更值得读——真正发生变化的不是写作哲学,而是这套协作机制开始从几个人之间的工作笔记,向一个需要治理编号、参与者和分发拓扑的技术基础设施演化。
前言
假设一个开发团队只有五个人。
有人在会议里提出一个协议修改,其他人都听到了;有人写了一页草稿,直接复印几份放到桌上;两份文档标题重名,也不是什么大事,因为大家知道“你说的是哪一份”。
现在把参与者换成分布在 UCLA、SRI、Utah、UCSB、RAND、Lincoln Laboratory、BBN、ARPA、SDC 等不同机构的一群工程师。
问题立刻变了:
1 | |
RFC 10 解决的就是这些问题。
它的标题仍然是 Documentation Conventions(文档约定),并且开门见山:
1 | |
这意味着阅读 RFC 10 时,真正需要问的并不是:
“它规定了哪些文档格式?”
而是:
为什么 RFC 3 才发布几个月,就已经需要修订?哪些规则必须保持不变,哪些运行细节已经跟不上工作组扩张?
答案非常有意思。
RFC 10 几乎完整保留了 RFC 3 最重要的几条原则:
- Membership is not closed;
- 任何站点、任何人都可以产生 NWG Note;
- 内容可以只是一个想法、建议、实现技巧,甚至只有问题没有答案;
- 文档应该 timely rather than polished;
- 一篇 Note 最短只需要一句话;
- “写下来了”不等于“有权威”;
- 标题不要求唯一。
真正修改的主要是:
1 | |
换句话说,RFC 10 面对的主要不是“写作规范不够好”,而是一个典型的系统扩容问题:
协议设计社区正在变大,原来靠少数人彼此认识就能维持的协作方式,需要开始显式管理身份、编号、路由和目录。
读懂 RFC 10,真正有价值的不是记住 1969 年某个人的电话号码。
而是看懂一套技术协作机制怎样从:
1 | |
逐渐长出:
1 | |
这些结构。
这套机制后来当然发生了巨大变化。今天 RFC 不再是“一句话也可以”的最终出版物,正式 RFC 通常从 Internet-Draft 开始,经讨论、评审、修订、批准和编辑后才获得 RFC 编号。
但如果想理解为什么现代技术组织喜欢用:
1 | |
把尚未定稿的设计放进一个可讨论、可追踪的公共空间,RFC 10 是一篇很好的早期样本。
RFC 基本信息
| 项目 | 内容 |
|---|---|
| RFC | RFC 10 |
| Official Title | Documentation conventions |
| 发布时间 | 1969 年 7 月 29 日 |
| 作者 | S. D. Crocker / Steve Crocker,UCLA |
| Status | Unknown,属于现代分类建立前的 Legacy Stream |
| Updates | 无 |
| Updated by | RFC 24、RFC 27、RFC 30 |
| Obsoletes | RFC 3 |
| Obsoleted by | RFC 16 |
| 原文 | RFC 10 |
| RFC Editor 信息页 | RFC 10 Info |
这里最容易误解的是 Status: Unknown。
RFC 10 发布于现代 IETF Standards Track、BCP、Informational、Historic 等完整分类体系出现之前,因此不能把 Unknown 理解成:
1 | |
它是一份 Legacy RFC。
RFC Editor 当前还明确给出了它的演化关系:
1 | |
同时 RFC 24、27、30 又在后续继续更新这套 Documentation Conventions。
这看起来不像今天干净的版本树,原因在于这些最早期 RFC 本来就不是按后来成熟的 Updates / Obsoletes 语义设计的;今天看到的关系,是对早期文档演化历史的结构化整理。
RFC 10 在当时也不是“互联网标准”。
它更接近:
Network Working Group 用来规定自己怎样产生、编号和分发技术工作笔记的一份运行规则。
为什么会有这篇 RFC
RFC 10 要解决的问题,只有和 RFC 3 对照起来才真正清楚。
1969 年 4 月的 RFC 3 已经建立了最基本的规则:
1 | |
这套机制在一个极小的工作组中足够好。
RFC 3 列出的 Network Working Group 核心成员主要来自:
1 | |
文档分发名单只有 6 个联系人,RFC 编号由:
1 | |
分配。
几个月以后,RFC 10 列出的参与者已经扩展到:
1 | |
分发点也扩展到:
1 | |
一共 9 个。
这里最重要的变化不是“名单多了几个人”。
而是系统规模发生了变化。
一个只有三四个机构的讨论组,可以大量依赖:
1 | |
当参与者不断增加,这种隐式知识就会开始失效。
可以把 RFC 3 到 RFC 10 的变化看成一个很典型的扩容过程:
flowchart LR
A[少量站点<br/>人员彼此熟悉]
B[更多站点加入]
C[编号冲突风险上升]
D[分发路径变复杂]
E[联系人与地址需要维护]
F[协作规则必须显式化]
A --> B
B --> C
B --> D
B --> E
C --> F
D --> F
E --> F
已有方法哪里不够
RFC 3 的原则本身没有失效。
事实上,RFC 10 几乎逐字保留了最核心的 CONTENT 部分。
真正不足的是它的运行配置。
编号负责人需要变化
RFC 3:
1 | |
RFC 10 改成:
1 | |
RFC 10 没有解释为什么换人,因此不能伪造“作者认为应该由 UCLA 中心化管理”之类的结论。
但从系统角度可以明确看到:
RFC 编号需要一个单一协调点,否则“任何人都能写”很容易变成“任何人都能随便占号”。
开放作者权和受控命名空间并不矛盾。
反而是二者必须同时存在:
1 | |
分发名单需要扩容
RFC 3 只要求作者站点把一份副本发给 6 个联系人。
RFC 10 扩成 9 个。
这意味着文档系统已经出现了最朴素的 fan-out distribution(扇出分发):
1 | |
作者不负责给每一位工程师复制几十份。
作者只负责把:
1 | |
送到每个分发节点。
然后:
1 | |
也就是:
各站点自己完成本地复制。
这是一个很合理的层次:
1 | |
如果把所有复制压力都放在作者身上,随着站点数量增加,成本会迅速失控。
联系方式已经成为系统状态
RFC 10 比 RFC 3 多了一个很长的:
1 | |
章节。
里面记录:
- 邮寄地址;
- 机构;
- 电话;
- 分机号。
并且作者明确写:
1 | |
这句话其实很重要。
它说明 RFC 分发系统已经遇到一个所有分布式目录都会遇到的问题:
目录里的地址会过期。
一个联系人:
1 | |
都会使分发拓扑失效。
所以 RFC 10 不只是在管理“文档”。
它实际上还在维护:
1 | |
RFC 10 的真正设计目标
从原文可以把目标重建成四层。
Problem
1 | |
Goal
建立一个足够轻量的机制,使技术意见能够:
1 | |
Constraint
当时没有今天的:
1 | |
更关键的是,ARPANET 本身甚至还没有成为一个稳定可用的文档分发网络。
所以制度必须建立在:
1 | |
之上。
Non-goal
RFC 10 并没有定义:
- 一篇 Note 怎样“批准”为标准;
- 怎样判定 Working Group Consensus;
- 怎样做技术评审;
- 怎样解决两种冲突提案;
- 怎样定义 Standards Track;
- 怎样管理版权或知识产权;
- 怎样验证文档作者身份;
- 怎样进行数字签名;
- 怎样保证副本可靠送达;
- 怎样给一篇 RFC 发布修订版而保持同一个编号。
这些今天看起来很重要的机制,要么当时根本还没有形成,要么并不是 RFC 10 要解决的问题。
RFC 10 的设计范围非常窄:
先保证想法能够低门槛地产生,并进入一个有编号、有作者、有分发路径的共享讨论空间。
核心内容
RFC 10 最值得理解的不是 CONTENT / FORM / DISTRIBUTION / ADDRESSES 四个标题本身,而是它们组合以后形成的四个关键设计选择。
开放写作,但拒绝“文档天然有权威”
RFC 10 最核心的一段和 RFC 3 基本不变。
它允许 NWG Note 是:
- 一个抽象观点;
- 一个具体实现技巧;
- 没有背景说明的建议;
- 一个没有答案的问题;
- 最短只有一句话。
同时明确提出:
1 | |
这不是随便降低质量标准。
它解决的是两个不同但相关的问题。
问题 1:写成文字以后,人们会自动赋予它权威
RFC 10 明确担心:
1 | |
也就是一旦某个设计写成一份有标题、有编号、有作者的文档,读者很容易把它理解成:
1 | |
但 Network Working Group 当时正处于探索期。
如果只有“已经足够正确”的东西才能被编号,很多真正需要讨论的错误假设根本不会被暴露出来。
所以 RFC 10 的选择是:
1 | |
而不是:
1 | |
收益是:
1 | |
代价也很明显:
1 | |
这一点直到今天仍然重要:
RFC Number 从来不自动等于 Internet Standard。
现代 RFC 已经有更明确的 Stream、Status 和审批流程来解决这个问题;1969 年的做法则更原始,主要依靠文化约定告诉参与者:
1 | |
作者可以分布式产生文档,但编号必须全局唯一
RFC 10 仍然坚持:
1 | |
这是高度去中心化的作者模型。
但如果每个站点都自行给文档编号,就会立刻出现经典的分布式 ID 冲突:
1 | |
于是 RFC 10 采用:
1 | |
即:
flowchart LR
A[UCLA Author]
B[SRI Author]
C[RAND Author]
D[Steve Crocker / UCLA<br/>Serial Number Authority]
E[RFC N]
F[RFC N+1]
G[RFC N+2]
A --> D
B --> D
C --> D
D --> E
D --> F
D --> G
RFC 3 的编号负责人是 Bill Duvall / SRI,RFC 10 改成 Steve Crocker / UCLA。
负责人是谁是历史配置。
真正长期有效的设计思想是:
开放生产内容,不等于开放生成全局唯一身份。
命名空间需要协调。
标题可以重复,所以 Serial Number 才是真正的 Identity
RFC 10 再次明确:
1 | |
这句话非常容易被忽略。
如果标题不唯一,那么:
1 | |
都不能作为文档主键。
实际上:
1 | |
就有多篇叫 Documentation Conventions。
这意味着 RFC 系列很早就做出了一个正确的信息系统设计:
1 | |
可以类比:
1 | |
这让引用和演化关系成为可能。
如果后来有人写:
1 | |
不会因为标题重复而产生歧义。
分发采用“跨站点单副本 + 本地复制”的两级结构
RFC 10 的 Distribution 不是一个无聊的通讯录。
它实际上定义了一种分层复制策略。
作者站点只负责:
1 | |
各站点负责:
1 | |
可以表示为:
flowchart TD
A[Author Site]
U[UCLA Contact]
S[SRI Contact]
R[RAND Contact]
B[BBN Contact]
U1[UCLA Local Readers]
S1[SRI Local Readers]
R1[RAND Local Readers]
B1[BBN Local Readers]
A -->|one copy| U
A -->|one copy| S
A -->|one copy| R
A -->|one copy| B
U -->|local reproduction| U1
S -->|local reproduction| S1
R -->|local reproduction| R1
B -->|local reproduction| B1
为什么不让作者直接把文档寄给所有读者?
因为作者并不知道每个机构内部到底有多少人需要阅读。
把责任拆开以后:
1 | |
这是一个很典型的层次化扩展策略。
代价是:
1 | |
如果一个站点联系人失效,整个站点可能收不到新文档。
于是 RFC 10 才必须增加 ADDRESSES,并要求大家纠正过期信息。
这四个设计并不是独立知识点。
它们共同构成一套可以运行的协作系统:
1 | |
关键机制与工作流程
RFC 10 没有网络报文,因此这里最值得“跑起来”的不是 Packet,而是它定义的 RFC 产生与传播流程。
假设 RAND 的 John Haefner 发现当前 Host-Host Protocol 有一个问题:
两个 Host 同时建立连接时,现有规则是否会产生竞态?
他甚至还没有答案。
按照 RFC 10,这并不妨碍他发一份 NWG Note。
正常路径:一份 RFC 怎样进入工作组
第一步:作者形成一个尚未成熟的问题
此时作者掌握的是:
1 | |
RFC 10 明确允许这种情况。
它没有要求:
1 | |
这一步的设计目标是:
1 | |
第二步:文档获得 Serial Number
RFC 10 规定:
1 | |
因此作者不能自己决定:
1 | |
编号器维护全局序列。
Steve Crocker 在后来的 RFC 8700 回忆中补充说,他当时会等 Note 完成后才分配编号,以减少编号序列中的空洞。
这条“完成后再编号”是后来的历史回忆,不是 RFC 10 正文规则,因此需要和 RFC 10 本身区分开来。
第三步:加上最小元数据
RFC 10 要求每份 Note 至少带:
1 | |
可以看成一个极简 Header:
1 | |
这些字段各自解决不同问题:
| 字段 | 谁生成 | 谁使用 | 为什么需要 |
|---|---|---|---|
Network Working Group |
文档作者 | 所有读者 | 表明所属文档系列 |
Request for Comments: X |
编号负责人提供 X,作者写入 | 读者、后续 RFC | 稳定唯一引用 |
| Author | 作者 | 读者 | 知道意见来源 |
| Affiliation | 作者 | 读者 | 知道其机构上下文 |
| Date | 作者 | 读者 | 判断时间顺序和历史语境 |
| Title | 作者 | 人类读者 | 快速识别主题,但不承担唯一身份 |
如果 Title 重复,没有问题。
如果 RFC Number 重复,就会破坏整个系列的引用能力。
所以:
1 | |
才是这套系统最关键的标识字段。
第四步:作者站点向分发节点各发送一份副本
RFC 10 列出 9 个分发联系人。
作者不需要知道:
1 | |
他只需要把文档送到站点入口。
sequenceDiagram
participant A as RAND Author
participant N as RFC Number Coordinator / UCLA
participant U as UCLA Contact
participant S as SRI Contact
participant B as BBN Contact
participant L as Local Readers
A->>N: 获取 Serial Number
N-->>A: RFC X
A->>A: 写入 Author / Affiliation / Date / Title
A->>U: One Copy
A->>S: One Copy
A->>B: One Copy
U->>L: Local Reproduction
这里没有:
1 | |
RFC 10 也没有定义文档可靠交付协议。
它依赖的是:
1 | |
所以这是一个管理制度,不是可靠传输协议。
第五步:其他人产生新的 RFC,而不是覆盖旧文档
RFC 10 自己就是一个最好的例子:
1 | |
从系统设计角度,这相当于:
1 | |
而不是:
1 | |
后续也继续如此:
flowchart LR
R3[RFC 3]
R10[RFC 10]
R16[RFC 16]
R24[RFC 24]
R27[RFC 27]
R30[RFC 30]
R3 -->|revision / obsolete| R10
R10 --> R16
R10 --> R24
R16 --> R24
R24 --> R27
R10 --> R27
R16 --> R27
R27 --> R30
R24 --> R30
R10 --> R30
R16 --> R30
这张图看起来比现代 SemVer 复杂,但它有一个非常有价值的性质:
历史不会因为规则改变而被静默覆盖。
Failure Path 1:两篇文档标题一样怎么办
RFC 10 已经明确允许:
1 | |
因此:
1 | |
可以同时对应多个 RFC。
定位完全依赖:
1 | |
结果:
1 | |
都可以共存。
这就是为什么“标题”只应该用于人类理解,而不应该承担系统 Identity。
Failure Path 2:两个作者同时想要下一个编号怎么办
RFC 10 没有描述一个并发算法。
它直接通过组织设计消除问题:
1 | |
因此编号冲突被转化为:
1 | |
代价也很明显:
1 | |
在几十篇 RFC、少量作者的规模下完全可接受。
如果这个系统一天产生几百万份文档,这种人工中心化方案当然无法扩展。
这就是典型的:
在当时规模下,选择最简单的足够方案,而不是提前构建全球分布式 ID 服务。
Failure Path 3:联系人地址过期怎么办
RFC 10 没有自动服务发现。
它的解决方法非常朴素:
1 | |
这本质上是:
1 | |
只要目录错误:
1 | |
就可能失败。
RFC 16、24、27、30 后来持续修改分发名单,正说明这个状态是动态的。
Failure Path 4:一个粗糙想法被误认为正式标准怎么办
RFC 10 的主要防御不是加一个:
1 | |
字段。
而是通过文化和命名降低误解:
1 | |
再明确声明:
1 | |
这相当于告诉所有读者:
1 | |
但这种机制依赖参与者理解共同文化。
随着规模扩大,它不够了。
所以现代 RFC 体系增加:
- Internet-Draft 与 RFC 的明确区分;
- Stream;
- Status;
- Working Group Review;
- IETF / IESG Review;
- RFC Production;
- 明确的 Updates / Obsoletes 元数据。
也就是说,早期靠文化解决的问题,后来逐渐被制度和机器可读元数据解决。
重点概念与术语
Network Working Group
**Network Working Group(NWG,网络工作组)**在 RFC 10 中仍然是一个相当非正式的协作群体。
RFC 10 甚至仍然使用:
1 | |
这种非常松的表达。
它不是今天 IETF 中拥有 Charter、Chair、Milestone 和正式流程的 Working Group。
读到 Working Group 时不能把现代组织结构倒灌回 1969 年。
Request for Comments
**Request for Comments(请求评论)**在 RFC 10 的语境里是真的字面意思。
这些 Note 的目标首先是:
1 | |
而不是:
1 | |
RFC 8700 后来明确回顾,最早的 RFC 目标是启动对话,而不是创建标准或最佳实践的永久档案。
NWG Note
RFC 10 中的 RFC 本质上仍然被描述为:
1 | |
它可以是:
- 哲学观点;
- 实现技巧;
- 明确问题;
- 很短的意见。
所以不能把 NWG Note 直接等同于今天发布完成的 Standards Track RFC。
Serial Number
**Serial Number(连续编号)**是整个系列的稳定 Identity。
它解决:
1 | |
RFC 10 中由 Steve Crocker / UCLA 分配。
Authoritative
RFC 10 中 **authoritative(权威性的)**是一个很核心的词。
作者担心:
1 | |
被误解成:
1 | |
所以 RFC 制度有意降低早期文档的权威外观。
Affiliation
作者不仅要写名字,还要写:
1 | |
因为当时协议设计高度依赖:
1 | |
这个上下文。
今天技术讨论中公司、项目或 Working Group 仍可能重要,但 RFC 作者身份模型已经不再等同于这份 1969 年站点名录。
Distribution
这里的 **Distribution(分发)**不是网络层 Multicast。
它指文档物理副本怎样传到各个研究站点。
Reproduction
**Reproduction(复制)**指各站点自己复制更多文档副本。
它让跨站点分发与站点内部分发解耦。
Legacy Stream
这是现代 RFC Editor 给早期文档使用的历史分类。
它提醒读者:
1 | |
Obsoletes / Updated by
这些是今天 RFC Editor 为历史文档整理出的演化关系。
对于 RFC 10:
1 | |
不要把它理解成现代软件包里干净的:
1 | |
早期 RFC 的修订关系更像一系列增量工作笔记。
需要特别注意的点
RFC 10 不是一篇新的协议规范,而是 RFC 3 的修订版
它最核心的内容哲学几乎没有改变。
真正的变化集中在:
1 | |
所以如果把 RFC 10 写成“RFC 文档格式包含四个字段”,就会错过它为什么需要存在。
它本质上是:
协作系统扩容后的运行配置更新。
SHOULD 不能套 RFC 2119 的现代规范性语义
RFC 10 写:
1 | |
但 RFC 2119 是 1997 年才发布的。
RFC 8174 又在 2017 年进一步说明规范性关键词的使用方式。
因此 RFC 10 的 should 只是当时普通英文语境下的规定性表达,不能机械解释成现代:
1 | |
那种精确定义。
“任何人都可以写”不是“今天任何人都可以直接发布 RFC”
RFC 10 的:
1 | |
是在一个很小的 ARPANET 研究共同体中说的。
今天仍然可以开放参与 IETF,也可以公开提交 Internet-Draft,但正式 RFC 的产生流程已经不同。
RFC Editor 当前明确说明:
1 | |
所以:
1 | |
并不等于:
1 | |
“Timely rather than polished”今天更像 Internet-Draft / Draft PR,而不是最终 RFC
Steve Crocker 在 RFC 8700 中明确指出,今天早期、未成熟想法通常通过:
1 | |
交流。
正式 RFC 则已经变成:
1 | |
的出版物。
因此不能用 RFC 10 给今天的最终标准文档质量低下找借口。
RFC 16 “Obsoletes RFC 10”非常反直觉
RFC Editor 当前元数据明确:
1 | |
但 RFC 16 正文只有一个非常具体的变化:
MIT 现在也应该接收所有 Network Working Group memos,并给出 Abhai Bhushan 的地址和电话。
从内容看,它更像:
1 | |
而不是重新定义 RFC 10 的全部 Documentation Conventions。
这正说明早期 RFC 的 Obsoletes 关系不能完全按现代“大版本替换全部规范”理解。
后来的 RFC 24 又明确说:
1 | |
把两者重新合并成一份完整规则。
“Updated by RFC 24、27、30”与“Obsoleted by RFC 16”同时存在,不是数据库错误就能简单解释掉
按现代线性版本思维,很容易觉得:
1 | |
因为这些后续文档明确把多个旧 Note 一起列为修订基础。
RFC 27:
1 | |
RFC 30:
1 | |
所以正确的历史理解不是:
1 | |
而是:
1 | |
RFC 10 没有定义共识机制
它告诉你:
1 | |
却没有告诉你:
1 | |
这不是一个小缺口。
它说明 1969 年的 RFC 机制主要是:
1 | |
还不是完整的:
1 | |
RFC 10 没有可靠交付协议
分发规则是:
1 | |
但没有:
- ACK;
- Delivery Receipt;
- Retry;
- Timeout;
- Duplicate Detection。
如果某份纸质材料没送到,它没有协议层恢复机制。
这说明:
RFC 10 定义的是社会/组织流程,不是计算机可靠消息协议。
联系地址直接写进 RFC 今天已经明显过时
RFC 10 公开列出:
- 个人办公地址;
- 电话号码;
- 分机。
这是当时分发系统必须依赖的数据。
今天这些信息大多由:
1 | |
维护。
把易变化的运行时通讯录直接固化进长期技术文档,会带来明显的陈旧问题。
RFC 16、24、27、30 不断改名单,已经证明了这一点。
RFC 10 没有现代安全和身份认证机制
如果从现代威胁模型看,会马上问:
1 | |
RFC 10 没有数字签名、PKI 或身份验证机制。
不能据此批评 1969 年设计“没有安全意识”,因为它运行在规模很小、机构明确的研究共同体里。
但这确实属于:
1 | |
而不是今天可以原样复制的安全模型。
从今天的视角重新看这篇 RFC
今天仍然成立的设计思想
最值得保留的第一点,是:
早期讨论和最终标准应该是两个不同阶段。
RFC 10 通过降低 Note 门槛解决这个问题。
现代流程则通过:
1 | |
把两个阶段显式分开。
第二点是:
稳定 Identity 比漂亮标题重要。
RFC Number 作为不可混淆的编号,直到今天仍然是整个 RFC Series 最核心的引用方式。
第三点是:
开放参与与受控命名空间可以同时存在。
任何人可以提出设计,不代表任何人可以随意制造一个已占用的 RFC Number。
第四点是:
历史版本不应被静默覆盖。
RFC 3 没有因为 RFC 10 出现就消失。
RFC 10 也没有因为 RFC 24 出现就被修改成另一份内容。
旧文档保留下来,新文档显式描述关系。
对于架构决策记录,这仍然是非常优秀的原则。
已经发生变化的部分
最大的变化是:
1 | |
RFC 8700 对这个演化说得很清楚:
早期 RFC 的主要目标是:
1 | |
而不是:
1 | |
今天,RFC Editor 明确说明 RFC 通常从 Internet-Draft 开始,经过不同 Stream 的讨论、评审和批准,再由 RFC Production Center 编辑并正式发布。
所以现代结构更像:
flowchart LR
A[Idea]
B[Mailing List / Discussion]
C[Internet-Draft]
D[Review / Revision]
E[Stream Approval]
F[RFC Production Center]
G[RFC Number]
H[Published RFC]
A --> B --> C --> D --> E --> F --> G --> H
RFC 10 把:
1 | |
和:
1 | |
放得很近。
今天它们已经被清楚拆开。
另一个变化是编号机制。
RFC 10:
1 | |
今天 RFC Number 是在文档被批准并进入正式出版流程后,由 RFC Production 体系分配。
再有就是分发。
RFC 10:
1 | |
今天:
1 | |
分发问题已经从:
1 | |
变成:
1 | |
已经过时的历史设计
RFC 10 中最明显已经过时的是固定人名分发列表。
它把系统路由写成:
1 | |
这种模式规模一大就会出现:
1 | |
RFC 24 已经开始显示这个问题。
它不再像 RFC 10 那样用具体姓名定义 Network Working Group,而改成:
1 | |
也就是说:
1 | |
开始让位于:
1 | |
这是一种重要的扩展性改进。
固定电话和邮寄地址同样属于历史实现细节。
人工单点编号在当时规模足够简单,但今天如果用于互联网级文档生产也明显不可扩展。
最重要的过时点则是:
1 | |
今天已经通过更完整的文档生命周期和元数据解决这个问题。
现代工程中的对应物
现代软件组织里的内部 RFC Process,通常和 RFC 10 有非常强的结构相似性:
1 | |
GitHub Issue / Pull Request 也有类似结构:
1 | |
Architecture Decision Record(ADR)也经常采用:
1 | |
作为稳定 ID,并通过:
1 | |
保留历史演化。
这些现代实践并不一定直接“源自 RFC 10”。
更准确的说法是:
它们在解决同一类协作系统问题,因此自然出现了类似设计:开放产生内容、稳定标识、显式版本关系和可追踪历史。
这篇 RFC 带来的影响
RFC 10 最直接的影响不是某个网络协议字段,而是它本身形成了一条清晰的 Documentation Conventions 演化链。
直接协议影响:RFC 文档规则持续扩容
从 RFC Editor 和后续原文可以得到这条链:
flowchart LR
R3[RFC 3<br/>April 1969<br/>Initial Conventions]
R10[RFC 10<br/>July 1969<br/>Revision]
R16[RFC 16<br/>Aug 1969<br/>MIT Added]
R24[RFC 24<br/>Nov 1969<br/>Consolidated Revision]
R27[RFC 27<br/>Dec 1969<br/>Distribution Update]
R30[RFC 30<br/>Feb 1970<br/>Further Expansion]
R3 --> R10
R10 --> R16
R10 --> R24
R16 --> R24
R24 --> R27
R10 --> R27
R16 --> R27
R27 --> R30
RFC 10 相比 RFC 3:
1 | |
RFC 16 又加入:
1 | |
作为 NWG Memo 接收点。
RFC 24 把参与者定义从具体姓名升级为:
1 | |
并把分发名单扩展到:
1 | |
RFC 27 进一步增加到:
1 | |
RFC 30 则达到:
1 | |
其中已经出现:
- Carnegie-Mellon;
- Raytheon;
- Stanford;
等更多机构。
这个增长链非常具体地说明:
Documentation Conventions 并不是一次写完的“格式规范”,而是在随着网络社区扩张持续调整自己的分发拓扑。
直接影响:稳定编号最终成为整个 RFC Series 的核心引用机制
RFC 10 没有发明 RFC Number——RFC 3 已经规定了 Serial Number。
但 RFC 10 继续确认并运行了这个机制。
后来无论 RFC 制度怎样变化:
1 | |
稳定编号始终是核心引用方式。
今天 RFC 的标题可能:
- 被复用;
- 被修改;
- 非常长;
- 在不同文档中相似。
但:
1 | |
永远准确指向一个确定的历史出版物。
这就是一个非常成功的 Identity Design。
思想影响:开放性留下来了,但“低门槛”迁移到了 Draft 阶段
RFC 8700 对五十年演化的回顾非常重要。
它明确指出:
早期 RFC:
1 | |
目标是:
1 | |
今天 RFC:
1 | |
而那些尚未成熟的技术想法,则更多通过:
1 | |
流动。
也就是说,RFC 10 的核心思想没有完全消失,而是发生了分层迁移:
1 | |
这是一个很重要的制度演化。
它没有否定 RFC 10 的:
1 | |
而是把它放到了更合适的生命周期阶段。
思想影响:开放参与从“小组文化”变成正式流程原则
RFC 10 写:
1 | |
今天 RFC Editor 对 IETF 流程的说明仍然强调:
1 | |
不要求参与者必须属于某家公司或机构。
当然,中间经过了几十年的组织和流程演化,不能把今天 IETF 的开放治理简单说成“RFC 10 直接定义的”。
但可以可靠地说:
早期 NWG 就已经把非封闭参与作为明确规则,而开放参与后来一直是互联网标准协作文化的重要组成部分。
思想影响:技术文档开始成为工程过程本身,而不是项目结束后的说明书
RFC 10 的世界里:
1 | |
文档不是:
1 | |
而是:
1 | |
这和今天:
- Design RFC;
- ADR;
- Proposal;
- Internet-Draft;
- Pull Request Review;
有非常强的共通结构。
更重要的是,这种做法留下了完整的“失败设计”历史。
如果早期工程师只保存最终 NCP 或 TCP/IP,我们今天就无法看到:
1 | |
RFC 10 本身就是一个很好的例子:
它不是一份今天仍有效的规则,却精确记录了:
1969 年 7 月,一个快速扩张的技术共同体是怎样管理自己的知识流动的。
总结
RFC 10 当时真正解决的,不是“Markdown 应该怎么写”这种格式问题。
它面对的是一个更基础的协作系统问题:
当网络协议不再由同一个房间里的几个人讨论,而开始跨多个站点、多个机构并行推进时,怎样让不成熟的技术意见仍然能够快速进入讨论,同时又保证它们可识别、可引用、可分发?
它给出的答案非常简单:
1 | |
RFC 10 最关键的设计思想不是“所有 RFC 都应该粗糙”。
而是:
早期技术讨论必须有足够低的进入成本,但低门槛不能以失去身份、引用和传播能力为代价。
这也是它最聪明的地方。
它同时选择了:
1 | |
这些组合让一个很松散的研究群体拥有了一套最低限度、但真正可以运行的协作协议。
当然,RFC 10 本身也暴露了时代限制。
它依赖:
1 | |
规模一扩大,名单就不断过期,于是很快出现:
1 | |
持续更新分发系统。
后来更大的变化则是:
1 | |
与:
1 | |
被拆成两个不同阶段。
今天的设计逻辑已经演化为:
1 | |
但如果把这些现代组织和工具全部拿掉,底层逻辑仍然和 RFC 10 非常接近:
1 | |
今天的软件工程师仍然值得读 RFC 10,原因并不是它能教你写现代 RFC。
而是它展示了一个非常容易被忽略的事实:
大型技术系统不仅需要机器之间的协议,也需要设计这些机器协议的人之间有一套协议。
RFC 10 写的,正是后者。