BlindPost BlindPost ← 所有文章
English简体中文繁體中文

为什么 BlindPost 能撑得起 10 万人的群

WhatsApp 群上限 1,024 人。Signal 1,000 人。Telegram supergroup 能再多一些,但靠分片硬撑。大多数即时通讯软件都卡在几千人这一档 —— 因为它们的服务器必须把每条群消息分发(fanout)给每个成员:N 个成员就复制 N 份、路由 N 份、推送 N 次。

BlindPost 不是这样。对我们来说,发一条群消息更像发布一篇文章,而不是寄信。作者发布一次,任何有这篇"文章"的地址、又拿到"钥匙"的人,都可以来读。阅读人数没有理论上限 —— 因为"发布"这一步不会因为读者变多而变难。

我们的服务器就是存这篇加密的"文章"。任何持有群密钥的人(也就是成员)可以来拉、来解密。没有 fanout、没有按人头复制、没有成员名单。下面用标准密码学的层面讲清楚这套架构。

一条普通的群消息在普通 messenger 里走了哪些步骤

你在 WhatsApp 群里发了一条消息,服务器大致做这些事:

  1. 消息到达服务器,地址是 "ABC 群"。
  2. 服务器查 ABC 群的成员表 — 假设有 1,000 人。
  3. 服务器给这 1,000 个人每人的投递队列各 push 一份消息 envelope。
  4. 1,000 部手机各自收到一份。

这就是服务端 fanout:一条入站消息变成 N 条出站推送。服务器的 CPU、带宽、存储都跟成员数线性相关,再乘上历史发过的所有群消息。人数到几千之后这道数学就开始算不平了,所以 WhatsApp 死守 1,024 这个数。

BlindPost 的群是怎么搭出来的

BlindPost 的一个"群",在底层就是一个 X25519 公钥。仅此而已。我们的服务器在"群"那一列存的,是这个公钥的 base58 编码。

你创建一个群的时候,客户端:

  1. 在本地生成一对 X25519 密钥。
  2. 把公钥那一半当作群的永久标识符。
  3. 把私钥那一半,通过端到端加密,分发给你邀请的每个成员。

BlindPost 里"成员资格"的定义只有一句:谁持有这把群私钥,谁就是成员。我们的服务器上没有任何"成员名单"。成员的进群退群,本质上是私钥的进圈出圈 —— 服务器没办法枚举这个圈。

两层标识符

仔细的读者可能注意到一个尴尬的推论:既然"群就是一把 X25519 公钥",那这把密钥一旦轮换(下文会讲为什么要轮换,踢人就是),群的"密码学标识符"也跟着变了。从服务器视角看这没事;从用户视角看("我的群是不是换 ID 了?")就有事。

所以每个 BlindPost 客户端给每个群维护两层标识符:

本文其他地方说"群的公钥标识符"的时候,指的都是密码学这一层。稳定的本地标签纯粹是给 UI 用的,让底层密钥轮换的时候用户感知不到任何"群变了"

一条群消息在 BlindPost 里走了哪些步骤

你给群发一条消息:

  1. 客户端临时生成一对 X25519 密钥,跟群的公钥做 ECDH 算出共享密钥,加密一次消息。
  2. 一份 envelope 发给服务器,接收方写群的公钥标识符。
  3. 服务器把这份 envelope 存进这个群的 channel。完事。

没有 fanout 这一步。你的发送方带宽是 O(1) —— 不管这个群是 5 个人还是 5 万人,你发出去的就这一份。

成员怎么收到消息:稀疏拉取(sparse pull)

成员自己决定什么时候拉。每个成员的客户端维护一个 cursor — 它在群 channel 里读到哪个 seq 了 — 隔段时间问服务器一次:"ABC 群里 seq N 之后还有新 envelope 吗?"

这就是稀疏拉取。每个客户端自己决定:

服务器把消息按群的公钥标识符索引存盘,问什么 range 给什么 range。它不跟踪谁在读、谁是成员、谁落后了。从服务器视角看,每次拉取都是"某个客户端要 ABC 群 seq N 之后的 envelope" —— 这个客户端可能是 10 万真人里的一个、可能是一个人五个设备里的一台、可能是个无聊的工具随便拿到公钥来拉看看。我们无从分辨。

成本结构整个翻了过来:

"成员数"这个值,在我们整套基础设施里压根不存在

顺带白送的隐私属性

我们不是主动想藏起群成员表的 — 我们就没地方写。服务器上根本没有"群成员"这张表。"谁在 ABC 群?" 这个问题没有数据支撑得起来。

传票最多能从我们这里拿到的是:"IP A 在某个时间窗内跟群公钥 B 之间有过加密字节往返"。A 是 B 群的成员、还是个拿着公钥乱拉的脚本 — 我们没办法告诉你。

代价

天下没有白吃的午餐:

但这些代价换回来的是:一个不知道你社交图的服务器,和一个"人数上限是你手机渲染极限决定的、不是我们集群分发能力决定的"群聊。

立即体验 BlindPost