# 性能优化 **本文引用的文件** - [src/index.ts](file://src/index.ts) - [src/server.ts](file://src/server.ts) - [src/websocket.ts](file://src/websocket.ts) - [src/class/websockethandler.ts](file://src/class/websockethandler.ts) - [src/class/httphandler.ts](file://src/class/httphandler.ts) - [src/signaling.ts](file://src/signaling.ts) - [src/log.ts](file://src/log.ts) - [client/src/signaling.js](file://client/src/signaling.js) - [client/src/peer.js](file://client/src/peer.js) - [client/src/sender.js](file://client/src/sender.js) - [client/src/logger.js](file://client/src/logger.js) - [client/public/js/stats.js](file://client/public/js/stats.js) - [client/public/onebyone/store.js](file://client/public/onebyone/store.js) - [client/src/memoryhelper.js](file://client/src/memoryhelper.js) - [package.json](file://package.json) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本指南围绕视频流服务器与前端 WebRTC 客户端的整体性能进行系统化优化,覆盖以下方面: - 内存管理优化:垃圾回收调优、内存泄漏检测与进程监控 - 并发处理优化:连接池配置、线程数调整、异步处理优化 - 资源限制设置:文件描述符、网络连接、CPU 使用率控制 - WebRTC 性能优化:编码参数、带宽自适应、网络质量监控 - 缓存策略:静态资源、API 响应、浏览器缓存 - 性能监控指标与基准测试方法 ## 项目结构 该项目采用前后端分离的结构: - 服务端基于 Express 提供 HTTP/WebSocket 信令与静态资源托管,同时支持 HTTPS - 客户端包含多种示例页面与 WebRTC 输入/渲染相关脚本,以及统计与日志工具 ```mermaid graph TB subgraph "服务端" IDX["入口: src/index.ts"] SRV["HTTP 服务器: src/server.ts"] WS["WebSocket 信令: src/websocket.ts"] WSH["WS 处理器: src/class/websockethandler.ts"] HTTPH["HTTP 信令处理器: src/class/httphandler.ts"] SIG["信令路由: src/signaling.ts"] LOG["日志: src/log.ts"] end subgraph "客户端" CLISIG["信令客户端: client/src/signaling.js"] PEER["Peer 连接: client/src/peer.js"] SENDER["输入发送: client/src/sender.js"] STATS["统计: client/public/js/stats.js"] STORE["质量分析: client/public/onebyone/store.js"] LOGGER["日志: client/src/logger.js"] end IDX --> SRV SRV --> WS SRV --> SIG WS --> WSH SIG --> HTTPH CLISIG --> |"WebSocket"| WS CLISIG --> |"HTTP 轮询"| SRV PEER --> |"WebRTC 统计"| STATS PEER --> |"WebRTC 统计"| STORE SENDER --> |"输入事件"| PEER LOG -.->|"服务端日志级别"| SRV LOGGER -.->|"客户端调试开关"| CLISIG ``` 图表来源 - [src/index.ts:1-109](file://src/index.ts#L1-L109) - [src/server.ts:1-90](file://src/server.ts#L1-L90) - [src/websocket.ts:1-118](file://src/websocket.ts#L1-L118) - [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479) - [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800) - [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25) - [src/log.ts:1-51](file://src/log.ts#L1-L51) - [client/src/signaling.js:1-292](file://client/src/signaling.js#L1-L292) - [client/src/peer.js:1-188](file://client/src/peer.js#L1-L188) - [client/src/sender.js:1-209](file://client/src/sender.js#L1-L209) - [client/public/js/stats.js:40-91](file://client/public/js/stats.js#L40-L91) - [client/public/onebyone/store.js:1130-1380](file://client/public/onebyone/store.js#L1130-L1380) - [client/src/logger.js:1-30](file://client/src/logger.js#L1-L30) 章节来源 - [src/index.ts:1-109](file://src/index.ts#L1-L109) - [src/server.ts:1-90](file://src/server.ts#L1-L90) ## 核心组件 - 服务端启动与 HTTPS/HTTP 选择、日志级别、信令类型与运行模式 - Express 中间件链:CORS、JSON/URL 编码、静态资源、Swagger 文档 - WebSocket 信令服务器与处理器:连接生命周期、广播、1对多模式、心跳 - HTTP 信令轮询:会话管理、超时清理、消息队列(offer/answer/candidate) - 客户端信令:WebSocket 与 HTTP 轮询双栈;WebRTC Peer 连接与统计 - 日志系统:服务端日志级别控制;客户端调试输出开关 章节来源 - [src/index.ts:13-109](file://src/index.ts#L13-L109) - [src/server.ts:14-89](file://src/server.ts#L14-L89) - [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118) - [src/class/websockethandler.ts:63-137](file://src/class/websockethandler.ts#L63-L137) - [src/class/httphandler.ts:110-120](file://src/class/httphandler.ts#L110-L120) - [src/signaling.ts:4-24](file://src/signaling.ts#L4-L24) - [src/log.ts:15-24](file://src/log.ts#L15-L24) - [client/src/signaling.js:30-97](file://client/src/signaling.js#L30-L97) - [client/src/peer.js:37-82](file://client/src/peer.js#L37-L82) ## 架构总览 服务端通过 Express 提供 HTTP 接口与静态资源,WebSocket 作为实时信令通道;HTTP 轮询作为备用方案。客户端根据配置选择 WebSocket 或 HTTP 轮询进行信令交互,WebRTC 数据通道承载媒体与控制消息。 ```mermaid sequenceDiagram participant C as "客户端" participant S as "Express 服务器" participant WS as "WebSocket 信令" participant HTTP as "HTTP 信令" participant H as "HTTP 处理器" C->>S : "GET /config" S-->>C : "{useWebSocket, mode, logging}" alt "WebSocket 模式" C->>WS : "建立连接" WS-->>C : "connect" C->>WS : "offer/answer/candidate/on-message" WS->>WS : "路由/广播/心跳" WS-->>C : "响应/广播" else "HTTP 轮询模式" C->>HTTP : "PUT /signaling (创建会话)" HTTP-->>C : "{sessionId}" loop "轮询" C->>HTTP : "GET /signaling?fromtime=..." HTTP->>H : "读取 offer/answer/candidate/disconnect" H-->>HTTP : "聚合消息" HTTP-->>C : "{messages, datetime}" end end ``` 图表来源 - [src/server.ts:25-41](file://src/server.ts#L25-L41) - [src/websocket.ts:27-115](file://src/websocket.ts#L27-L115) - [src/class/httphandler.ts:615-641](file://src/class/httphandler.ts#L615-L641) - [src/signaling.ts:6-24](file://src/signaling.ts#L6-L24) - [client/src/signaling.js:30-97](file://client/src/signaling.js#L30-L97) ## 详细组件分析 ### 服务端启动与运行模式 - 支持命令行参数:端口、HTTPS 证书、信令类型(websocket/http)、运行模式(public/private)、日志级别 - 自动选择 HTTP 或 HTTPS 监听,打印可用地址 - 信令类型校验与回退至默认值 - WebSocket 信令服务器初始化并注入运行模式 章节来源 - [src/index.ts:14-91](file://src/index.ts#L14-L91) ### HTTP 服务器与静态资源 - 开启 Morgan 日志(可配置) - CORS 允许任意来源 - 解析 JSON/URL 编码请求体 - 提供 /config、/signaling 路由、静态资源目录 - Swagger 文档初始化 - 头像上传接口:multer 存储、重命名、返回相对 URL 章节来源 - [src/server.ts:18-89](file://src/server.ts#L18-L89) ### WebSocket 信令服务器 - 基于 ws 的服务器实例绑定到 HTTP 服务器 - 连接生命周期:add/remove - 消息分发:connect/disconnect/offer/answer/candidate/ping/pong/broadcast/call-request/on-message - 心跳机制(注释掉的实现),可通过处理器扩展 章节来源 - [src/websocket.ts:15-118](file://src/websocket.ts#L15-L118) - [src/class/websockethandler.ts:404-430](file://src/class/websockethandler.ts#L404-L430) ### WebSocket 处理器(1对多模式与广播) - 私有模式:host 与多个 participants;offer/answer/candidate 按 participantId 路由 - 公共模式:全局广播 - 连接组管理:host/participants、参与者加入/离开通知 - 广播消息:支持按连接组或全局广播 - 心跳与超时(注释实现) 章节来源 - [src/class/websockethandler.ts:63-168](file://src/class/websockethandler.ts#L63-L168) - [src/class/websockethandler.ts:175-206](file://src/class/websockethandler.ts#L175-L206) - [src/class/websockethandler.ts:214-338](file://src/class/websockethandler.ts#L214-L338) - [src/class/websockethandler.ts:370-402](file://src/class/websockethandler.ts#L370-L402) ### HTTP 信令处理器(轮询模式) - 会话管理:创建/删除、连接集合、超时检测 - 消息存储:offer/answer/candidate 映射,断开连接记录 - 查询接口:/signaling、/offer、/answer、/candidate、/connection - 私有模式下的连接配对与跨会话消息路由 章节来源 - [src/class/httphandler.ts:110-120](file://src/class/httphandler.ts#L110-L120) - [src/class/httphandler.ts:218-232](file://src/class/httphandler.ts#L218-L232) - [src/class/httphandler.ts:398-407](file://src/class/httphandler.ts#L398-L407) - [src/class/httphandler.ts:492-501](file://src/class/httphandler.ts#L492-L501) - [src/class/httphandler.ts:549-558](file://src/class/httphandler.ts#L549-L558) - [src/class/httphandler.ts:615-641](file://src/class/httphandler.ts#L615-L641) ### 客户端信令与 WebRTC - WebSocketSignaling:连接建立、消息分发、发送 offer/answer/candidate/on-message - HTTP 轮询 Signaling:循环拉取消息、事件派发 - Peer:RTCPeerConnection 生命周期、ICE 候选收集、状态变化监听、重发 offer - Sender:鼠标/键盘/手柄/触摸输入采集与事件队列 - 统计:客户端侧统计计算(比特率、帧率、抖动、往返时间等) 章节来源 - [client/src/signaling.js:152-292](file://client/src/signaling.js#L152-L292) - [client/src/signaling.js:30-97](file://client/src/signaling.js#L30-L97) - [client/src/peer.js:37-82](file://client/src/peer.js#L37-L82) - [client/src/peer.js:124-130](file://client/src/peer.js#L124-L130) - [client/src/sender.js:14-188](file://client/src/sender.js#L14-L188) - [client/public/js/stats.js:40-91](file://client/public/js/stats.js#L40-L91) - [client/public/onebyone/store.js:1130-1380](file://client/public/onebyone/store.js#L1130-L1380) ### 日志系统 - 服务端:枚举日志级别、动态设置、格式化输出 - 客户端:调试开关、条件输出 章节来源 - [src/log.ts:15-24](file://src/log.ts#L15-L24) - [client/src/logger.js:3-29](file://client/src/logger.js#L3-L29) ## 依赖关系分析 - 服务端依赖:Express、ws、Morgan、Swagger、UUID、Multer - 客户端依赖:浏览器原生 WebRTC API、EventTarget、fetch ```mermaid graph LR P["package.json 依赖"] --> E["Express"] P --> W["ws"] P --> M["Morgan"] P --> SW["Swagger"] P --> U["UUID"] P --> MU["Multer"] E --> SRV["src/server.ts"] W --> WS["src/websocket.ts"] SRV --> SIG["src/signaling.ts"] SIG --> HTTPH["src/class/httphandler.ts"] WS --> WSH["src/class/websockethandler.ts"] ``` 图表来源 - [package.json:14-26](file://package.json#L14-L26) - [src/server.ts:1-14](file://src/server.ts#L1-L14) - [src/websocket.ts:1-6](file://src/websocket.ts#L1-L6) - [src/signaling.ts:1-4](file://src/signaling.ts#L1-L4) - [src/class/httphandler.ts:1-11](file://src/class/httphandler.ts#L1-L11) - [src/class/websockethandler.ts:1-11](file://src/class/websockethandler.ts#L1-L11) 章节来源 - [package.json:14-26](file://package.json#L14-L26) ## 性能考虑 ### 内存管理优化 - 垃圾回收调优 - 服务端:合理设置 Node.js 堆大小与 GC 参数(通过环境变量或启动脚本传入),避免大对象频繁分配与长生命周期持有 - 客户端:避免在事件回调中累积大量闭包引用;及时释放媒体轨道与数据通道 - 内存泄漏检测 - 服务端:启用堆快照与内存采样,关注 Map/Set 的增长趋势(如连接组、会话映射) - 客户端:使用浏览器开发者工具的内存面板,检查事件监听器与 DOM 引用是否正确清理 - 进程监控 - 服务端:定期记录内存使用、连接数、请求量;异常时触发重启或降级 - 客户端:统计页面生命周期内的内存峰值与抖动 章节来源 - [src/class/websockethandler.ts:19-37](file://src/class/websockethandler.ts#L19-L37) - [src/class/httphandler.ts:42-77](file://src/class/httphandler.ts#L42-L77) - [client/src/peer.js:184-186](file://client/src/peer.js#L184-L186) ### 并发处理优化 - 连接池配置 - 服务端:限制并发请求数与 WebSocket 连接数,结合负载均衡部署 - 客户端:合理设置轮询间隔,避免过于频繁的短连接请求 - 线程数调整 - Node.js:使用集群模式(cluster)或多进程部署,避免单进程阻塞 - 异步处理优化 - 服务端:将耗时操作(文件写入、统计计算)放入任务队列或子线程 - 客户端:WebRTC 统计与事件处理使用 requestAnimationFrame 或微任务 章节来源 - [src/server.ts:44-83](file://src/server.ts#L44-L83) - [client/src/signaling.js:49-91](file://client/src/signaling.js#L49-L91) ### 资源限制设置 - 文件描述符限制 - Linux:ulimit -n;Docker:--ulimit nofile;确保并发连接与文件上传场景充足 - 网络连接限制 - 服务端:限制每 IP 的连接数与速率;启用反向代理限流 - 客户端:合理设置轮询超时与重试次数 - CPU 使用率控制 - 服务端:限制并发任务数量;对高 CPU 操作(编码/解码统计)做节流 - 客户端:降低统计频率、减少不必要的事件派发 章节来源 - [src/server.ts:44-83](file://src/server.ts#L44-L83) - [client/public/js/stats.js:40-91](file://client/public/js/stats.js#L40-L91) ### WebRTC 性能优化 - 编码参数调整 - 服务端:通过信令协商合适的编解码器与参数(如分辨率、帧率、码率范围) - 客户端:根据网络质量动态调整发送轨道参数 - 带宽自适应 - 使用 WebRTC 的 BWE 与 REMB;客户端周期性上报统计,服务端下发降级指令 - 网络质量监控 - 客户端统计:比特率、帧率、抖动、丢包率、往返时间 - 服务端:聚合统计与告警阈值 ```mermaid flowchart TD Start(["开始"]) --> GetStats["获取 WebRTC 统计"] GetStats --> Compute["计算比特率/帧率/抖动/丢包率"] Compute --> Check{"是否异常?"} Check --> |否| End(["结束"]) Check --> |是| Adapt["调整编码参数/带宽"] Adapt --> SendCmd["通过信令下发降级指令"] SendCmd --> End ``` 图表来源 - [client/public/js/stats.js:40-91](file://client/public/js/stats.js#L40-L91) - [client/public/onebyone/store.js:1130-1380](file://client/public/onebyone/store.js#L1130-L1380) - [client/src/peer.js:124-130](file://client/src/peer.js#L124-L130) 章节来源 - [client/src/peer.js:37-82](file://client/src/peer.js#L37-L82) - [client/public/js/stats.js:40-91](file://client/public/js/stats.js#L40-L91) - [client/public/onebyone/store.js:1130-1380](file://client/public/onebyone/store.js#L1130-L1380) ### 缓存策略配置 - 静态资源缓存 - Express 静态托管:设置合理的 Cache-Control 与 ETag - 前端构建产物:版本化文件名,长期缓存 - API 响应缓存 - HTTP 信令:对只读查询设置短期缓存,结合 Last-Modified/ETag - 浏览器缓存设置 - 客户端脚本:强缓存;HTML:协商缓存 - 服务端:通过中间件统一设置缓存头 章节来源 - [src/server.ts:27-28](file://src/server.ts#L27-L28) - [src/server.ts:86](file://src/server.ts#L86) ### 性能监控指标与基准测试 - 指标 - 服务端:QPS、P95/P99 延迟、连接数、内存、GC 次数与暂停时间 - 客户端:首帧时间、卡顿次数、统计上报频率、丢包率、抖动 - 基准测试 - 使用压测工具模拟多路并发;对比 WebSocket 与 HTTP 轮询的延迟与稳定性 - WebRTC:不同分辨率/帧率组合下的端到端延迟与质量 章节来源 - [src/log.ts:15-24](file://src/log.ts#L15-L24) - [client/public/js/stats.js:40-91](file://client/public/js/stats.js#L40-L91) ## 故障排查指南 - WebSocket 连接异常 - 检查心跳实现与超时阈值;确认处理器中的连接移除逻辑 - HTTP 轮询堆积 - 检查会话超时清理与消息去重;优化轮询间隔 - 内存泄漏 - 关注 Map/Set 的清理时机;客户端事件监听器与 DOM 引用释放 - 日志定位 - 调整日志级别;区分服务端与客户端日志输出 章节来源 - [src/class/websockethandler.ts:404-430](file://src/class/websockethandler.ts#L404-L430) - [src/class/httphandler.ts:218-232](file://src/class/httphandler.ts#L218-L232) - [src/log.ts:30-50](file://src/log.ts#L30-L50) - [client/src/logger.js:3-29](file://client/src/logger.js#L3-L29) ## 结论 通过合理的内存管理、并发控制、资源限制与 WebRTC 统计监控,可在保证用户体验的同时提升系统的稳定性与吞吐能力。建议在生产环境中结合监控指标持续迭代优化策略,并针对不同部署场景(单机/集群/容器)制定差异化的性能基线。 ## 附录 - 启动与配置 - 服务端启动脚本与参数:端口、HTTPS、信令类型、运行模式、日志级别 - 客户端信令选择:WebSocket 或 HTTP 轮询 章节来源 - [package.json:5-12](file://package.json#L5-L12) - [src/index.ts:20-41](file://src/index.ts#L20-L41) - [client/src/signaling.js:152-292](file://client/src/signaling.js#L152-L292)