12.4.5 现代化选择——PartyKit:边缘计算的实时通信方案
一句话破题
PartyKit 是"边缘优先"的实时通信平台,它让你用最少的代码构建全球分布式的实时应用。
为什么选择 PartyKit
传统 WebSocket 服务器的问题:
- 单点部署:用户距离服务器越远,延迟越高
- 扩展困难:需要自己处理负载均衡和状态同步
- 运维负担:需要管理服务器、监控、日志等
PartyKit 的解决方案:
- 边缘部署:代码自动部署到全球各地的边缘节点
- 零运维:完全托管,无需关心基础设施
- 状态管理:内置持久化存储和状态同步
快速上手
bash
# 安装 CLI
npm install -g partykit
# 创建项目
npx create-partykit my-party
cd my-party服务端代码
typescript
// party/index.ts
import type { PartyKitServer, PartyKitConnection, PartyKitRoom } from 'partykit/server';
export default {
onConnect(connection: PartyKitConnection, room: PartyKitRoom) {
console.log(`${connection.id} 加入房间 ${room.id}`);
// 发送欢迎消息
connection.send(JSON.stringify({ type: 'welcome', roomId: room.id }));
// 广播给其他人
room.broadcast(
JSON.stringify({ type: 'userJoined', id: connection.id }),
[connection.id] // 排除当前用户
);
},
onMessage(message: string, connection: PartyKitConnection, room: PartyKitRoom) {
const data = JSON.parse(message);
// 广播消息给所有人
room.broadcast(
JSON.stringify({
type: 'message',
from: connection.id,
content: data.content,
timestamp: Date.now(),
})
);
},
onClose(connection: PartyKitConnection, room: PartyKitRoom) {
room.broadcast(
JSON.stringify({ type: 'userLeft', id: connection.id })
);
},
} satisfies PartyKitServer;客户端代码
tsx
'use client';
import { useEffect, useState } from 'react';
import PartySocket from 'partysocket';
export default function PartyChat({ roomId }: { roomId: string }) {
const [messages, setMessages] = useState<Array<{ from: string; content: string }>>([]);
const [input, setInput] = useState('');
const [socket, setSocket] = useState<PartySocket | null>(null);
useEffect(() => {
const partySocket = new PartySocket({
host: 'your-project.partykit.dev', // 或 localhost:1999 用于开发
room: roomId,
});
partySocket.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
if (data.type === 'message') {
setMessages((prev) => [...prev, { from: data.from, content: data.content }]);
}
});
setSocket(partySocket);
return () => {
partySocket.close();
};
}, [roomId]);
const sendMessage = () => {
if (socket && input.trim()) {
socket.send(JSON.stringify({ content: input }));
setInput('');
}
};
return (
<div>
{messages.map((msg, i) => (
<div key={i}>
<strong>{msg.from}:</strong> {msg.content}
</div>
))}
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
/>
<button onClick={sendMessage}>发送</button>
</div>
);
}PartyKit vs Socket.io
| 特性 | Socket.io | PartyKit |
|---|---|---|
| 部署方式 | 自托管服务器 | 边缘托管 |
| 全球延迟 | 取决于服务器位置 | 自动优化 |
| 扩展性 | 需要自己处理 | 自动扩展 |
| 持久化 | 需要外部数据库 | 内置存储 |
| 定价 | 服务器成本 | 按使用量付费 |
持久化状态
PartyKit 可以在边缘存储状态:
typescript
export default {
async onConnect(connection, room) {
// 获取存储的状态
const state = await room.storage.get('messages') || [];
connection.send(JSON.stringify({ type: 'history', messages: state }));
},
async onMessage(message, connection, room) {
const data = JSON.parse(message);
// 保存到存储
const messages = await room.storage.get('messages') || [];
messages.push({ from: connection.id, content: data.content });
await room.storage.put('messages', messages.slice(-100)); // 保留最近 100 条
room.broadcast(message);
},
} satisfies PartyKitServer;AI 协作指南
- 核心意图:让 AI 帮你使用 PartyKit 构建实时功能。
- 需求定义公式:
"请帮我用 PartyKit 实现一个实时协作白板,支持多人同时绘图和状态同步。" - 关键术语:
PartyKit、边缘计算 (edge computing)、room、broadcast、持久化存储
避坑指南
- 房间 ID 设计:房间 ID 决定了用户分组,设计时要考虑业务逻辑。
- 消息大小限制:单条消息有大小限制,大数据考虑分片传输。
- 冷启动延迟:首次连接可能有短暂延迟,做好 loading 状态处理。
