用 WebRTC 与 Cloudflare Durable Objects 构建一个零知识 P2P 同步引擎

用 WebRTC 与 Cloudflare Durable Objects 构建一个零知识 P2P 同步引擎

💡 原文中文,约16300字,阅读约需39分钟。
📝

内容提要

H.A.N. 是一款本地优先的 Markdown 笔记本,通过 WebRTC 点对点同步,无需账号、云存储和服务器费用。它利用 URL 哈希片段传递密钥实现零知识加密,以 16KB 分片和背压控制解决传输限制,并通过清单比对、墓碑和冲突分叉处理同步冲突。信令由 Cloudflare Workers 短暂中转,连接后即断开,实现端到端加密与零基础设施成本。

🔎

延伸解读

零知识密钥交换的巧妙之处

文章利用 URL 哈希片段(#)传递 AES-GCM 密钥,因为浏览器不会将片段发送给服务器。这意味着密钥仅存在于设备本地,信令服务器只能看到房间 ID,无法解密任何笔记内容。这种设计在无账号体系下实现了真正的零知识,但需注意:密钥通过二维码光学传输,若二维码被他人窥屏,安全性即被破坏。

分片与背压:解决 WebRTC 传输瓶颈

WebRTC DataChannel 在不同浏览器中有不同的单消息大小限制(Safari 64 KiB,Chromium 256 KiB),直接发送大文件会崩溃。文章采用 16 KiB 分片加 8 字节包头,并引入背压控制(高水位 128 KiB 暂停,低水位 64 KiB 恢复),避免缓冲区溢出。这套机制使数 GB 数据传输成为可能,但分片重组增加了延迟和内存开销,需权衡分片大小。

墓碑与冲突分叉:同步中的删除与编辑冲突

分布式同步中,简单的“缺失即同步”会导致已删除笔记复活。H.A.N. 通过软删除墓碑记录删除时间,同步时比较时间戳决定是否恢复。对于并发编辑,系统不覆盖而是生成冲突副本,让用户手动合并。这种非破坏性策略保障了数据安全,但可能产生大量冲突文件,需要用户定期清理。

基础设施零成本的实现与限制

信令服务器基于 Cloudflare Workers 和 Durable Objects,利用 WebSocket 休眠和短暂房间,实现零服务器费用。但该方案依赖 Cloudflare 免费额度,若信令请求量极大或房间长期存在,可能触发计费。此外,P2P 连接在对称 NAT 下可能失败,文章未提及 TURN 回退,实际部署需考虑网络兼容性。

Q&A

H.A.N. 的 P2P 同步引擎如何实现零知识加密?

H.A.N. 使用 Web Crypto API 生成 256 位 AES-GCM 对称密钥,并通过 URL 哈希片段(#)传递密钥。由于浏览器不会将哈希片段发送给服务器,密钥仅存在于客户端,服务器无法获取。所有通过 WebRTC DataChannel 传输的数据都使用 AES-GCM-256 加密,每条消息使用唯一的 12 字节 IV,确保端到端加密。

WebRTC DataChannel 发送大消息时遇到大小限制怎么办?

H.A.N. 实现了应用层分片协议,将加密后的载荷切分为 16 KiB 的分片,每个分片前添加 8 字节头部(包含消息 ID、分片索引和总分片数)。接收端使用 MessageReassembler 按 messageId 重组乱序到达的分片,确保大文件可靠传输。

如何避免同步时缓冲区溢出导致消息丢失?

H.A.N. 采用背压流控机制:设置高水位线(128 KiB)和低水位线(64 KiB)。当 channel.bufferedAmount 超过高水位线时,暂停发送并等待 bufferedamountlow 事件;当缓冲区排空到低水位线时恢复发送。这防止了 SCTP 发送缓冲区溢出,保证大数据量传输的稳定性。

H.A.N. 如何解决笔记删除后同步时“复活”的问题?

H.A.N. 使用软删除墓碑(Tombstone)机制。删除笔记时,在本地元数据中记录一条墓碑条目(包含删除时间戳),而不是直接删除文件。同步时,设备会传输墓碑信息。如果对端笔记的更新时间早于墓碑的删除时间,则确认删除并清除本地副本;如果对端在删除后修改过笔记,则保留更新版本。

当两台设备同时修改同一笔记时,H.A.N. 如何处理冲突?

H.A.N. 执行非破坏性冲突分叉:将来自对端的笔记写盘并附加冲突时间戳后缀(如“Work/Project (Conflict 2026-09-04-154500).md”),本地版本保持不变。同时弹出通知,提示用户使用内置的 Git 可视化 diff 查看器并排审阅两个版本,确保任何编辑都不会丢失。

H.A.N. 的信令服务器为什么能保持零成本?

信令服务器基于 Cloudflare Workers 和 Durable Objects 构建,采用“Drop on Open”原则:仅在 WebRTC 连接建立前短暂中转 SDP/ICE 消息,一旦 DataChannel 打开,立即断开 WebSocket 连接。Durable Objects 支持 WebSocket 休眠,空闲连接不计费,且房间是短暂的,无需数据库清理,因此基础设施成本为 $0.00/月。

H.A.N. 如何保证不同设备上笔记编辑的实时更新?

H.A.N. 通过全局 EventBus 和 BroadcastChannel 实现跨标签页和组件的实时更新。当远程笔记通过 WebRTC 写入本地存储后,会触发 'note:reloaded' 事件,并广播到其他浏览器标签页。当前打开的笔记编辑器监听该事件,若笔记 ID 匹配则立即重新加载内容,无需手动刷新。

🏷️

标签

➡️

继续阅读