你的社交数据,凭什么归平台所有?用 Cloudflare 搭建去中心化社交应用
一个反复发生的故事一个平台突然关闭或者改变商业模式你多年积累的关注者、帖子、社交图谱一夜之间或烟消云散或被锁在另一家公司的服务器里。这件事在互联网历史上发生过很多次而且还会继续发生。问题的根源在于在传统的中心化社交平台上你的账号和数据属于平台而不属于你。ATProtoAuthenticated Transfer Protocol认证传输协议想从协议层面解决这个问题。Bluesky 是目前最大的 ATProto 应用但 ATProto 本身并不等于 Bluesky——它是一套开放协议任何人都可以在上面构建应用。这篇文章以 Cloudflare 官方博客中的一个实战项目为线索讲清楚两件事ATProto 的核心设计思想是什么以及如何在 Cloudflare 的无服务器平台上从零搭建一个真正可用的去中心化社交应用。ATProto 的基本逻辑数据归用户协议做担保理解 ATProto需要先放下平台的思维框架换成协议的视角。身份你的账号是一个域名在 ATProto 里用户身份以**句柄Handle**的形式存在格式是一个合法的域名比如alice.example.com。这不只是个名字。协议通过 DNS 的 TXT 记录来验证句柄的所有权——你在域名的_atproto子域下放一条特定的 TXT 记录任何人都可以独立验证这个账号确实属于这个域名的持有者不需要依赖任何中心化的认证机构。句柄背后是一个去中心化标识符DIDDID 再指向用户的**个人数据服务器PDS**的位置。PDS 可以是 Bluesky 官方提供的也可以是用户自己搭建的或者任何第三方服务商——这个选择权完全在用户手里。数据签名的、可验证的、跨应用互通的用户发布的所有内容都存储在自己的**个人仓库Repository**里并且经过密码学签名。这意味着数据的真实性可以被任何人独立验证不需要信任某个中心服务任何应用都可以读取和构建在这些数据之上无需获得原始应用的许可即使某个应用下线数据本身依然存在于用户的仓库中。所有数据类型通过Lexicon这套类似 JSON Schema 的语言来定义保证了不同应用之间的数据可以互相理解和复用。事件流全局可订阅的社交网络动态当用户在任意应用中发布内容时这个变更会触发一个事件发布到中继节点Relay再广播到全局事件流中。任何应用不管它是不是原始发布者都可以订阅这个事件流来获取整个网络的实时动态。这就是去中心化的真正含义仓库、中继、应用三者相互独立可以由不同的运营者运行却共享同一套数据网络。Statusphere最小可用的去中心化社交应用Cloudflare 博客选用了 ATProto 团队官方的示例项目Statusphere作为演示载体。它的功能极其简单用户只能发布单个 emoji 表情作为状态更新。正因为足够简单Statusphere 反而是理解 ATProto 数据流动方式的最佳起点。它的数据格式Lexicon 定义只有两个字段{status:单个 emoji,createdAt:发布时间}这个记录会被写入用户的个人仓库带上密码学签名然后广播到全局事件流。任何订阅了这个 Lexicon 类型xyz.statusphere.status的应用都能实时看到这个更新。在 Cloudflare 上的无服务器实现Cloudflare 博客的核心工程价值在于展示了如何不依赖任何自管服务器用 Cloudflare 的开发者平台组件拼出一个完整的 ATProto 应用。整个项目的所有资源都可以在免费套餐内运行。Workers业务逻辑的执行层Cloudflare Workers 是整个应用的入口负责处理所有 HTTP 请求用户登录、数据读取、状态发布。Workers 部署在全球 300 多个节点上代码距离用户通常不超过 50ms。KV缓存身份解析结果ATProto 的身份解析涉及两步先通过 DNS 把句柄解析为 DID再通过 DID 找到用户 PDS 的位置。这两步的结果变化非常不频繁但每次请求都要用到。Workers KV 是这类场景的自然选择——全球分布、低延迟读取、没有存储量限制。身份解析结果和用户的 OAuth Session 数据都存在 KV 里客户端只持有一个不透明的 Session ID。D1关系型数据的持久化用户发布的状态更新在写入 ATProto 仓库的同时也会写入 Cloudflare D1一个基于 SQLite 的分布式数据库确保页面能立即反映最新状态不依赖事件流的延迟。Durable ObjectsWebSocket 实时推送每个打开首页的用户都维持着一个与 Durable Object 的 WebSocket 连接。当有新的状态更新时Worker 向 Durable Object 发送广播指令后者遍历所有活跃连接将更新推送给每一个在线用户。Durable Objects 有一个重要特性休眠Hibernation。当没有消息需要广播时Durable Object 可以进入休眠状态不占用计算资源但 WebSocket 连接保持活跃。只有收到广播请求时才被唤醒处理完后再次休眠。这对于控制成本至关重要。最棘手的工程问题实时事件流遇上无服务器前面描述的都是应用内的操作——用户通过 Statusphere 本身发布状态流程是闭环的。但 ATProto 的设计允许用户通过任何应用发布xyz.statusphere.status类型的记录这些记录同样应该出现在 Statusphere 的时间线上。为此应用需要订阅全局事件流服务Jetstream。问题来了订阅 Jetstream 需要一个持久的 WebSocket 客户端连接但无服务器平台的 Worker 不能无限期运行。这是一个经典的架构矛盾团队给出了两种解法。方案一Cron Trigger 定时轮询纯无服务器用 Cloudflare Workers 的Cron Trigger功能每分钟触发一次 Worker 执行从持久存储中读取上次处理到的游标cursor一个微秒级时间戳以这个游标为起点连接 Jetstream拉取从该时刻起的新事件处理完比当前时间更新的事件后主动关闭 WebSocket 连接Worker 结束执行。这套方案完全在无服务器模型内运行无需任何外部进程。代价是更新有最长约一分钟的延迟对于早期项目和原型来说这是完全可以接受的折衷。游标存储在 Durable Object 的持久存储中即使实例重启也能从正确的位置续传不遗漏任何事件。方案二轻量监听进程混合模式如果需要真正的实时性可以在任意一台机器哪怕是家里的树莓派上运行一个极简的监听进程它维持一条到 Jetstream 的持久 WebSocket 连接收到新事件时通过 HTTP 请求推送给 Cloudflare Worker自身不对外暴露任何端口没有公网 IP没有数据库。这个进程的职责单一几乎不需要维护。等应用规模扩大后可以将其替换为Cloudflare Queues获得批处理和失败重试的能力。这种混合模式在工程上是务实的选择——它并没有破坏无服务器的核心价值无需管理复杂的服务端基础设施只是用一个最轻量的方式填补了平台目前的能力空缺。工程选型为什么用了 Rust WASM项目最初尝试用 TypeScript 实现因为 ATProto 的官方核心库就是用 TypeScript 编写的Workers 也对 TypeScript 有一流支持。但 ATProto 的 TypeScript 库依赖了一些与 Cloudflare 边缘运行时不兼容的 Node.js API直接使用行不通。最终选择了Rust WASM将 Rust 代码编译为 WebAssembly运行在 Workers 上。ATProto 的 Rust 社区库atrium虽然还在活跃开发中但已足够完整作者基于一个已有的 Rust 版 Statusphere 实现进行改造较快地完成了可用原型。对于有意在 Cloudflare Workers 上构建 ATProto 应用的开发者博客建议向 TypeScript 官方库贡献 PR修复其与 Serverless 运行时的兼容性问题——这将使生态的门槛大幅降低。平台的一个现有限制与未来方向Durable Objects 目前支持在持有长连接 WebSocket服务端时进入休眠但暂不支持在持有长连接 WebSocket客户端比如连接到 Jetstream 的那种时休眠。这正是 Statusphere 需要 Cron Trigger 方案或外部监听进程来绕过这一限制的原因。未来如果 Durable Objects 能够支持客户端 WebSocket 连接的休眠整个 Cron Trigger 方案就可以用一个在 Durable Object 内部运行的 Jetstream 监听器来替代彻底消除这种绕路设计让架构更加简洁。总结这个项目从表面看是一个 emoji 状态更新的玩具应用但它真正在演示的是一种新的应用构建范式数据主权层面ATProto 把账号所有权还给了用户——身份基于 DNS 验证数据经过密码学签名任何应用都无法单方面没收用户的社交资产。基础设施层面Cloudflare 的 Workers KV D1 Durable Objects 这套组合让开发者可以在几乎零运维的情况下构建出具备全球分发、实时推送、持久化存储能力的完整应用——而且免费套餐就够用。工程思路层面Cron Trigger 应对实时流的方案是一个很好的示范承认平台当前的限制找到在约束内工作的最简洁方案而不是强行绕开约束引入不必要的复杂度。项目代码完全开源一键部署按钮可以直接把整套环境克隆到你自己的 Cloudflare 账号下是上手 ATProto 开发的实用起点。参考来源Cloudflare Blog — “Serverless Statusphere: a walk through building serverless ATProto applications on Cloudflare’s Developer Platform”