PartyKit — Cloudflare Durable Objects 上的实时协作 framework
是什么
PartyKit 是一个专门用来写”多人实时房间”的 framework——白板、协同光标、聊天室、在线状态、小型实时游戏,写起来就像写一个普通的 HTTP 路由。
日常类比:你想开一家网吧,传统做法要租机房、买交换机、雇网管、写排队系统。PartyKit 像是一个”只交押金就给你一间会议室”的服务——你只管定”进门规则”和”传话规则”,房间本身(人在哪台机器、消息怎么转发、断线怎么续)平台帮你管。
底层是 Cloudflare Durable Objects:每个”房间”对应一个全球唯一的 actor,状态只在这一个点上写,但全世界任何节点都可以连进来。它让”实时单点一致性”变得便宜。
为什么重要
你想做一个”多人光标白板”,自己从零搭要解决:
- WebSocket 网关怎么扩容(一个房间的人必须落到同一台机器,否则消息广播得跨进程)
- 状态放哪(Redis Pubsub?自建 Node 集群?数据库?)
- 全球延迟(用户在新加坡,机器在弗吉尼亚,光速也要 200ms)
- 断线重连、房间销毁、冷启动持久化……
PartyKit 把这些全部包进 “写一个 PartyServer 类” 这一个动作。代价是把自己绑在 Cloudflare Workers/Durable Objects 生态里。2024 年它被 Cloudflare 收购,变成官方协作框架。
核心要点
1. 一个房间 = 一个 Durable Object 实例
export default class MyRoom implements Party.Server { constructor(readonly room: Party.Room) {} onConnect(conn: Party.Connection) { /* 有人进来 */ } onMessage(msg: string, sender: Party.Connection) { this.room.broadcast(msg, [sender.id]) // 广播给除自己外所有人 }}类比:Party.Room 是这个会议室的”房间号 + 当前在场名单 + 黑板”,Party.Connection 是每个进来的人。
2. 路由 = 房间 ID
https://my-app.partykit.dev/parties/main/<roomId> 这个 URL 自动路由到 roomId 对应的 DO 实例。第一次访问就启动,没人时回收。
3. 持久化在房间内
this.room.storage.put("doc", state) 直接写在房间本地——不需要外部数据库,DO 自带 KV。重启从 storage 读回。
4. 不是只能 WebSocket
PartyServer 也能接 HTTP(onRequest)和定时器(alarm())。你可以把它当成”带状态的小 Worker”。
历史小故事(可跳过)
- 2023 年初:Sunil Pai(前 React core team)观察到”实时协作功能”是每个 SaaS 都想加但都做不好的事。他做了 PartyKit 的第一版,主张”应该和写一个 React 组件一样简单”。
- 2023 年中:开源后快速积累 1k+ stars,社区催生 y-partykit、partysocket 等周边。
- 2024 年 4 月:Cloudflare 宣布收购 PartyKit。Sunil Pai 加入 Cloudflare 团队,PartyKit 继续以独立品牌运营,但路线图开始与 Cloudflare Workers / Durable Objects / Hibernation API 深度对齐。
- 意义:证明了”edge runtime + 单点 actor”是实时协作的可行底座;也意味着这种 framework 长期会下沉成平台原语。
实践案例
案例 1:和 yjs 配合做协同文档
PartyKit 不自己做 CRDT,但提供 y-partykit adapter:
import { onConnect } from "y-partykit"export default class YjsRoom { async onConnect(conn, room) { return onConnect(conn, room, { persist: true }) }}客户端用 y-partykit/provider 替换 y-websocket,剩下 Yjs 文档怎么 merge 完全不变。Yjs 管”两份 JSON 怎么合并”,PartyKit 管”消息怎么到达每个人 + 文档存哪里”。
案例 2:和 liveblocks 的对比关系
| 维度 | PartyKit | Liveblocks |
|---|---|---|
| 抽象层级 | server primitive(你写 onMessage) | 产品 SDK(presence/storage/comments 现成) |
| 部署 | 自己的 Cloudflare 账号 | 全托管 SaaS |
| 计费 | 按 DO 请求/CPU | 按 MAU |
| 退路 | 就是 Workers DO,能完全自管 | 锁在 Liveblocks 平台 |
简化判断:要快速做产品功能选 Liveblocks;要可控、能下沉到底层选 PartyKit。
案例 3:和 sharedb / automerge 对比
- ShareDB:OT 算法 + 自托管 Node 集群,老牌方案,运维重
- Automerge:CRDT 库,需要自己接传输层;可以用
automerge-repo+ PartyKit 当存储层 - PartyKit:不绑算法,谁的 adapter 都能接;卖点是免运维 edge runtime
案例 4:最简单的”在线人数”房间
export default class Counter implements Party.Server { count = 0 constructor(readonly room: Party.Room) {} onConnect() { this.count++ this.room.broadcast(JSON.stringify({ count: this.count })) } onClose() { this.count-- this.room.broadcast(JSON.stringify({ count: this.count })) }}20 行实现一个全球同步的”当前在线人数”。换成传统架构,至少要一个 Redis + 一个 WS 网关 + 心跳逻辑。这就是 framework 真正在替你省的事。
踩过的坑
-
DO 是单点:一个房间所有写都串行到一个进程。游戏每秒 1000 条事件、房间 500 人时 CPU 会顶到 50ms 限额。文档 / 白板 / 聊天没问题,高频 OLTP 不要硬塞。
-
broadcast不是真广播:每个连接独立 send,房间 1000 人时一次 broadcast 是 1000 次 send。大房间需要”分桶”或上 PubSub 兜底。 -
冷启动延迟:DO 首次访问要冷启 actor,~50-200ms。空房间预热可以靠 cron 定时 ping。
-
本地开发和生产行为不一致:
partykit dev单机起一个 server,没真正模拟 DO 的”全球单点”约束。多 tab 测协同没问题,跨区域测一定要部署到 partykit.dev。 -
被 Cloudflare 收购后路线图绑死 Workers:独立 partykit npm 还能用,但新 feature 都向
cloudflare:workers的 DO API 靠拢。新项目可以直接用 Workers + DO + WebSocket Hibernation,省一层抽象。
适用 vs 不适用场景
适用:
- 协同光标 / 在线状态 / 实时白板 / 多人聊天 / 简单实时游戏
- 已经在 Cloudflare 生态(Workers / Pages / R2)
- 想避开自建 WS 网关 + Redis Pubsub 的运维负担
不适用:
- 单房间高频写(>100 ops/s 持续)→ 用消息队列 + 分片
- 需要严格强一致跨房间事务 → 用真正的数据库(Postgres / Spanner)
- 不能依赖 Cloudflare(合规 / 多云策略) → 选 ShareDB / 自建 Yjs server
学到什么
- “一个房间一个 actor”是个被低估的模型:解决了”实时多人”最难的状态分片问题
- DX-first 的 framework 价值在”消除决策”:不让你选 Redis vs Pubsub vs Kafka,而是直接给你写一个类
- 被巨头收购后,独立 framework 通常变薄:能力沉到平台原语里,框架本身退化成”教学包装”
延伸阅读
- 官方文档:docs.partykit.io(看 Concepts → Rooms 这一章就懂模型)
- Sunil Pai 演讲:The Future of Real-Time Apps(讲为什么从 React 跑去做 framework)
- Cloudflare 收购公告:解释了为什么 DO + Hibernation 是更彻底的底座
- 进阶题目:自己实现一个”会议室白板”——光标用 broadcast,画笔轨迹用 Yjs 文档,同时跑通
关联
- yjs —— PartyKit 最常见的搭档:Yjs 管 CRDT 合并,PartyKit 管房间和持久化
- automerge —— 另一种 CRDT 选择,automerge-repo 也能跑在 PartyKit 上
- liveblocks —— 同类竞品,更产品化、更托管;PartyKit 更底层、更可控
- sharedb —— 老牌 OT 方案,自托管 Node;和 PartyKit 是两条工程路线