MonkeyCode 网络架构WebSocket、SSE与实时协作的技术选型AI编程工具对网络架构的要求远高于普通Web应用。代码编辑需要实时同步、AI响应需要流式传输、终端操作需要双向通信、文件变更需要即时推送。MonkeyCode 在网络架构上经历了多次迭代最终形成了一个混合通信方案。通信需求分析MonkeyCode 有以下通信需求场景数据方向实时性要求数据量代码编辑双向100ms小增量AI对话服务端→客户端流式中终端I/O双向50ms中文件同步双向500ms大容器状态服务端→客户端推送小为什么不用单一方案纯WebSocket的问题AI流式响应用WebSocket有些重 — 每次AI调用都需要管理连接状态文件上传用WebSocket效率低 — 二进制数据需要额外编码重连逻辑复杂 — WebSocket断开后需要恢复所有频道的状态纯HTTP的问题代码编辑的实时性不够 — HTTP轮询延迟太高终端I/O无法实现 — 需要全双工通信MonkeyCode 的混合方案WebSocket (长连接)\n├── 终端I/O频道\n├── 代码编辑同步频道\n├── 容器状态通知频道\n└── AI对话控制频道\n\nSSE (服务端推送)\n└── AI流式响应\n\nHTTP REST (请求-响应)\n├── 文件上传/下载\n├── AI模型调用非流式\n└── 用户认证/管理WebSocket设计频道复用单一WebSocket连接通过频道复用传输不同类型的数据// 客户端→服务端\n{\n channel: terminal,\n action: input,\n data: ls -la\\n,\n seq: 12345\n}\n\n// 服务端→客户端\n{\n channel: terminal,\n event: output,\n data: total 24\\ndrwxr-xr-x 5 root root 4096 ...,\n seq: 12346\n}消息确认机制关键消息如代码编辑操作需要确认// 发送方\nws.send({\n channel: editor,\n action: edit,\n data: { op: insert, pos: 42, text: const },\n ackRequired: true,\n msgId: msg_789\n});\n\n// 接收方确认\nws.send({\n channel: editor,\n action: ack,\n msgId: msg_789,\n serverTimestamp: 1717833600000\n});心跳保活// 客户端每30秒发送心跳\nsetInterval(() {\n if (ws.readyState WebSocket.OPEN) {\n ws.send(JSON.stringify({ channel: system, action: ping }));\n }\n}, 30000);\n\n// 服务端60秒无心跳则认为断线\nconst HEARTBEAT_TIMEOUT 60000;SSE设计AI流式响应AI模型响应使用SSE而不是WebSocket原因SSE是单向的更符合请求→流式响应的模式SSE自动重连浏览器原生支持SSE基于HTTP更容易做负载均衡和缓存// 前端\nconst eventSource new EventSource(\n /api/ai/stream?sessionId${sessionId}prompt${encodedPrompt}\n);\n\neventSource.addEventListener(token, (event) {\n const chunk JSON.parse(event.data);\n appendToEditor(chunk.text);\n});\n\neventSource.addEventListener(done, (event) {\n const summary JSON.parse(event.data);\n console.log(生成完成共${summary.totalTokens}个token);\n eventSource.close();\n});\n\neventSource.addEventListener(error, (event) {\n handleStreamError(event);\n});代码编辑同步OT算法代码编辑同步是技术难度最高的部分。MonkeyCode 使用OTOperational Transformation算法// 编辑操作定义\ntype EditOp {\n type: insert | delete | replace;\n position: number;\n text?: string;\n length?: number;\n};\n\n// 两人同时编辑时的冲突解决\nfunction transform(op1: EditOp, op2: EditOp): [EditOp, EditOp] {\n // 如果两个操作影响不同的区域不需要变换\n if (op1.position (op1.length || 0) op2.position) {\n return [op1, op2];\n }\n // 如果op1在op2前面调整op2的位置\n if (op1.type insert) {\n return [op1, { ...op2, position: op2.position op1.text.length }];\n }\n // 其他情况...\n}断线恢复网络断开时的恢复流程客户端检测到断线进入离线模式本地操作存入队列定时尝试重连重连成功后发送离线期间的编辑操作服务端合并操作并推送最新的完整状态class OfflineManager {\n private pendingOps: EditOp[] [];\n private lastSyncVersion: number 0;\n\n onOffline() {\n console.log(进入离线模式编辑操作将暂存本地);\n }\n\n onEdit(op: EditOp) {\n this.pendingOps.push(op);\n localStorage.setItem(pendingOps, JSON.stringify(this.pendingOps));\n }\n\n async onOnline() {\n // 发送离线期间的编辑\n const result await api.sync({\n fromVersion: this.lastSyncVersion,\n ops: this.pendingOps\n });\n \n if (result.conflicts.length 0) {\n // 有冲突提示用户手动解决\n this.showConflictDialog(result.conflicts);\n } else {\n this.pendingOps [];\n localStorage.removeItem(pendingOps);\n }\n }\n}性能优化消息压缩— 代码编辑操作使用二进制编码而非JSON减少50%传输量批量发送— 快速连续的编辑操作合并后发送16ms窗口内差异同步— 文件同步只传输变更部分CDN加速— 静态资源通过CDN分发降低API服务器压力总结AI编程工具的网络架构需要在实时性、可靠性、效率之间找到平衡。MonkeyCode通过WebSocketSSEHTTP的混合方案为不同场景选择了最合适的通信方式。这种分而治之的思路也适用于其他实时性要求高的Web应用。GitHubgithub.com/chaitin/MonkeyCode