摘要

  • NNTP 把全局唯一的 Message-ID 与“讨论组名称+文章编号”这一服务器本地键分开;一篇交叉发布的文章因此可以有多个编号,却仍然只是一篇文章。
  • Xref 汇总最后一台新闻服务器上的组与位置,阅读软件可据此避免重复处理同一篇交叉发布文章。
  • 服务服务器通常会删除收到的 Xref,再按自己的存储视图重写。变化的是本地归档回执,不是文章正文,也不是全局身份。

第二次看见同一篇文章

读者在一个讨论组里看完一篇文章,随后打开另一个已订阅的组,又遇到相同内容。标题一样,正文一样,文章编号却不同。它是副本、重复投稿,还是另一篇文章?

在 Netnews 的模型里,这些推断都未必成立。作者可能把一篇文章同时交叉发布到两个组。服务器通常只保存一篇文章,却在每个组的本地索引中为它安排一个位置。若阅读器只记住第一个编号,就可能把第二个坐标误认为另一篇文章。

Xref 为此提供一张紧凑的归档回执。它列出最后处理该文章的服务器,以及文章在这台服务器的哪些组、哪些位置可见。它没有给文章再造一个名字,而是把多个本地坐标连回同一篇文章。

这里隐藏着分布式系统中常被忽略的边界:身份回答“这是哪一篇文章”,位置回答“某一台服务器此刻从哪里提供它”。Usenet 同时需要两者,也需要两者不能互相冒充。

三种键,不是一个万能编号

RFC 3977 描述了 NNTP 存储和检索文章时使用的三类键。第一类是全局唯一的 Message-ID;第二类由讨论组名称和该组内的文章编号组成;第三类是服务器记录的到达时间戳。

组与编号组成的键在本地有严格含义:同一服务器的同一组中,一个编号只能指向一篇文章,一篇文章也不能在同一组里拥有两个编号。但一篇交叉发布文章可以同时属于多个组,于是每个组都能给它一个键,而且这些编号可以不同。

RFC 同时明确指出,这种键不要求全局唯一。相同的组名和编号,在不同服务器上可以指向不同文章。编号按各台服务器自己的到达顺序分配,所以换服务器就等于换坐标系。

NNTP 的 GROUP 命令返回低水位、高水位和估算数量,并不保证两端之间的每一个编号都存在。文章可以被移除,也可以在规则允许的范围内以原编号恢复。缺号因此不是“全网删除”的证明,高编号也不是全球时间顺序。

编号承载的是本地到达、保留、过期、审核和修复政策留下的痕迹。它适合作为坐标,却不足以承担身份。

一篇文章,几层书架

RFC 5536 把交叉发布定义为将同一篇文章发往多个讨论组,并把它与“把相同文字分别发成多篇文章”区分开。服务器通常只保存一份文章,再从多个组索引到它。

Xref 正是这种扇出关系的表达。字段先写生成它的新闻服务器身份,随后列出一个或多个位置;每个位置把讨论组名称与文章定位符配对。传统 NNTP 定位符是十进制文章编号,但 RFC 允许实现使用其他形式。

服务器名不是装饰。它告诉软件后面的坐标属于哪一个命名空间。去掉这层范围,相同组名与编号可能在另一台服务器上指向完全不同的文章。保留范围,阅读器便能知道:这台服务器上的几个位置通向同一篇文章。

RFC 5536 说明,用户代理常用 Xref 避免多次处理交叉发布文章。读者在一个组里看过文章后,客户端可以把同一回执连接的其他位置一并标为已处理。这不仅减少烦扰,也保留了交叉发布的真实语义:一次发言面向多个受众,不应因此被计算成多篇独立文章。

声明去向与实际归档是两件事

Newsgroups 字段声明文章被发往哪些组;Xref 记录最后一台服务器实际把文章归档到哪里。RFC 5536 特别允许两者不同。

这种差异并非不一致,而是对本地控制面的诚实表达。某台服务器可能不承载所有组,也可能按审核或站点政策拒绝某些归档位置;保留与过期还会继续改变可见集合。若服务器只是把作者声明复制成回执,本地决定反而会被隐藏。

因此,Newsgroups 随文章表达声明的分发范围,Xref 则呈现某台服务器的存储视图。前者不应伪装成本地事实,后者也不能伪装成作者意图。

这张回执本来就可以被替换

RFC 1036 在 1987 年描述的 Xref,由本地主机名和从假脱机目录取得的“讨论组/消息编号”对组成。文档明确说,这些信息只对本地系统有价值,不应传输;其中的例子让同一篇消息在两个组里拥有两个编号。

后来的架构允许该字段在组件之间更有规则地流动,却没有把它升级为永久身份。RFC 5537 允许中继代理删除已有 Xref,再为自身用途添加一个。服务代理通常必须移除传入字段;除非采用保留发送站点定位符的特殊配置,它可以而且通常会在存储前写入自己的字段。

这种重写不是漏洞。RFC 5537 同时规定,中继与服务代理不得修改文章,只有 Path 与 Xref 是狭窄例外,正文不得改变。于是,本地位置元数据可以变化,文章本身仍保持不变。

这条规则揭示了设计核心:在保管边界上可以重写归档回执,因为回执记录的是服务器自己的归档决定,而不是作者创造的持久文章。

范围标记不是认证印章

字段中的服务器名很容易被误读为来源证明,但规范没有赋予它这种能力。它只告诉软件该如何解释后面的坐标,不是密码学签名,不验证作者,也不证明哪台机器最初接收了文章。

中继和服务代理能够删除并重建字段,本身就是反对“不可变来源证据”解释的理由。这里的非认证边界,是根据重写规则与规范中缺少认证承诺所得的审慎推论。Xref 可以是某台服务服务器视图的有用证据,但只能放在该服务器的信任与观测环境中理解。

当前 IANA 消息头字段注册表 仍将 Xref 列为标准 Netnews 字段,并指向 RFC 5536;Message-ID 与 Newsgroups 则分别登记。注册表提供共同词汇,并没有把文章身份、声明分发和本地位置合并成同一种权威。

编号的意义是“这里”

Xref 的历史成就不是发明更强的标识符,而是承认一篇文章可以拥有多个坐标,且下一台服务器可以改变这些坐标而不改变文章。

这避免了两种对称错误。把位置当身份,会在文章跨组或服务器视图变化时制造重复文章;把身份当位置,则会幻想一篇拥有全局名称的文章必然拥有一个全球通用地址,而 NNTP 从未承诺这一点。

官方证据不能说明今天有多少客户端仍使用 Xref,也不能单凭字段解释某个编号为何消失。它能确定的是机制的范围:Message-ID 回答“哪一篇文章”,Xref 回答“这台服务器把它放在哪里”。这种克制正是可靠性的来源。