SKILL.md
唯讀
名稱
websocket-engineer
描述
建置基於 WebSocket 或 Socket.IO 的即時通訊系統時使用。適用於雙向訊息傳送、透過 Redis 進行水平擴充、在線狀態追蹤以及房間/聊天室管理等情境。
WebSocket 工程師
核心工作流程
- 需求分析 — 評估連線規模、訊息流量與延遲需求
- 架構設計 — 規劃集群(clustering)、發布/訂閱(pub/sub)、狀態管理與故障移轉(failover)
- 實作開發 — 建置具備身份驗證、房間與事件處理機制的 WebSocket 伺服器
- 本地驗證 — 在進行擴充前,先測試連線處理、身份驗證及房間行為(例如:
npx wscat -c ws://localhost:3000);確認缺少或無效 Token 時會正確拒絕連線、驗證加入/離開房間事件以及訊息傳遞 - 水平擴充 — 在啟用轉接器(adapter)前,先確認 Redis 連線與發布/訂閱往返測試(pub/sub round-trip);設定黏性工作階段(sticky sessions),並透過跨多個執行個體(instances)的測試連線進行驗證;建立負載平衡機制的設定
- 系統監控 — 追蹤連線數、延遲、吞吐量與錯誤率;針對連線數驟增及錯誤率超越門檻設定警報通知
參考指南
根據開發情境載入對應的詳細指引:
| 主題 | 參考文件 | 載入時機 |
|---|---|---|
| 協定細節 | references/protocol.md |
WebSocket 握手(handshake)、數據框(frames)、ping/pong 機制、關閉代碼 |
| 擴充機制 | references/scaling.md |
水平擴充、Redis 發布/訂閱(pub/sub)、黏性工作階段(sticky sessions) |
| 設計模式 | references/patterns.md |
房間(rooms)、命名空間(namespaces)、廣播(broadcasting)、送達確認(acknowledgments) |
| 資安防護 | references/security.md |
身份驗證(Authentication)、授權(Authorization)、速率限制(rate limiting)、CORS |
| 替代方案 | references/alternatives.md |
Server-Sent Events (SSE)、長輪詢(long polling)、何時該選擇 WebSocket |
程式碼範例
伺服器端設定(整合身份驗證與房間管理的 Socket.IO)
import { createServer } from "http";
import { Server } from "socket.io";
import { createAdapter } from "@socket.io/redis-adapter";
import { createClient } from "redis";
import jwt from "jsonwebtoken";
const httpServer = createServer();
const io = new Server(httpServer, {
cors: { origin: process.env.ALLOWED_ORIGIN, credentials: true },
pingTimeout: 20000,
pingInterval: 25000,
});
// 身份驗證中介軟體 — 在建立連線前執行
io.use((socket, next) => {
const token = socket.handshake.auth.token;
if (!token) return next(new Error("Authentication required"));
try {
socket.data.user = jwt.verify(token, process.env.JWT_SECRET);
next();
} catch {
next(new Error("Invalid token"));
}
});
// 用於水平擴充的 Redis 轉接器
const pubClient = createClient({ url: process.env.REDIS_URL });
const subClient = pubClient.duplicate();
await Promise.all([pubClient.connect(), subClient.connect()]);
io.adapter(createAdapter(pubClient, subClient));
io.on("connection", (socket) => {
const { userId } = socket.data.user;
console.log(`connected: ${userId} (${socket.id})`);
// 線上狀態(Presence):將使用者標記為在線
pubClient.hSet("presence", userId, socket.id);
socket.on("join-room", (roomId) => {
socket.join(roomId);
socket.to(roomId).emit("user-joined", { userId });
});
socket.on("message", ({ roomId, text }) => {
io.to(roomId).emit("message", { userId, text, ts: Date.now() });
});
socket.on("disconnect", () => {
pubClient.hDel("presence", userId);
console.log(`disconnected: ${userId}`);
});
});
httpServer.listen(3000);
用戶端重新連線(搭配指數退避演算法)
import { io } from "socket.io-client";
const socket = io("wss://api.example.com", {
auth: { token: getAuthToken() },
reconnection: true,
reconnectionAttempts: 10,
reconnectionDelay: 1000, // 初始延遲時間 (ms)
reconnectionDelayMax: 30000, // 上限設定為 30 秒
randomizationFactor: 0.5, // 加入隨機抖動因子,避免驚群效應 (thundering herd)
});
// 當處於斷線狀態時,將待傳送的訊息暫存至佇列
let messageQueue = [];
socket.on("connect", () => {
console.log("connected:", socket.id);
// 清空佇列並補發訊息
messageQueue.forEach((msg) => socket.emit("message", msg));
messageQueue = [];
});
socket.on("disconnect", (reason) => {
console.warn("disconnected:", reason);
if (reason === "io server disconnect") socket.connect(); // 手動觸發重新連線
});
socket.on("connect_error", (err) => {
console.error("connection error:", err.message);
});
function sendMessage(roomId, text) {
const msg = { roomId, text };
if (socket.connected) {
socket.emit("message", msg);
} else {
messageQueue.push(msg); // 暫存至緩衝佇列直到連線恢復
}
}
開發規範與限制
務必執行 (MUST DO)
- 在負載平衡中使用黏性工作階段(sticky sessions,因 WebSocket 連線屬於有狀態連線,請求必須精確路由至同一個伺服器執行個體)
- 實作心跳機制/Ping-Pong 以即時偵測斷線狀態(僅靠 TCP keepalive 無法完整涵蓋所有異常)
- 善用房間(rooms)與命名空間(namespaces)管理訊息作用域,避免在應用程式邏輯中進行無謂的過濾
- 在斷線過渡期將訊息暫存至佇列,防止資料無聲遺失
- 在進行水平擴充前,務必預先規劃單一執行個體的連線承載上限
嚴格禁止 (MUST NOT DO)
- 在缺乏集群策略的情況下,直接將大量狀態常駐於記憶體中(應優先採用 Redis 或外部儲存)
- 在未明確處理 Upgrade 協定轉換的情況下,讓 WebSocket 與 HTTP 共用同一 Port
- 遺漏連線資源清理機制(如在線狀態紀錄、房間成員資格、未完成的計時器等)
- 未經負載壓力測試即直接上線 — 連線數驟增的物理特性與傳統 HTTP 流量衝擊截然不同
輸出範本
實作 WebSocket 功能時,請提供:
- 伺服器端設定檔(Socket.IO / ws 相關配置)
- 事件處理常式(包含連線、訊息傳遞、斷線清理)
- 用戶端函式庫整合(包含連線建立、事件監聯與重連機制)
- 水平擴充策略簡要說明
知識庫參考
Socket.IO, ws, uWebSockets.js, Redis adapter, sticky sessions, nginx WebSocket proxy, JWT over WebSocket, rooms/namespaces, acknowledgments, binary data, compression, heartbeat, backpressure, horizontal pod autoscaling




