⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议
Skip to content

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.ioPartyKit
部署方式自托管服务器边缘托管
全球延迟取决于服务器位置自动优化
扩展性需要自己处理自动扩展
持久化需要外部数据库内置存储
定价服务器成本按使用量付费

持久化状态

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)roombroadcast持久化存储

避坑指南

  • 房间 ID 设计:房间 ID 决定了用户分组,设计时要考虑业务逻辑。
  • 消息大小限制:单条消息有大小限制,大数据考虑分片传输。
  • 冷启动延迟:首次连接可能有短暂延迟,做好 loading 状态处理。