Files
video_socket-server/.qoder/repowiki/zh/content/开发指南/扩展开发.md
2026-05-16 13:24:02 +08:00

433 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 扩展开发
<cite>
**本文引用的文件**
- [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/class/offer.ts](file://src/class/offer.ts)
- [src/class/answer.ts](file://src/class/answer.ts)
- [src/class/candidate.ts](file://src/class/candidate.ts)
- [client/src/signaling.js](file://client/src/signaling.js)
- [client/src/peer.js](file://client/src/peer.js)
- [test/websockethandler.test.ts](file://test/websockethandler.test.ts)
- [package.json](file://package.json)
- [client/package.json](file://client/package.json)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本指南面向希望扩展视频信令服务器的开发者,系统讲解如何:
- 添加新的信令消息类型(如 Offer、Answer、Candidate 的扩展)
- 扩展 WebSocketHandler 与 HttpHandler 的消息处理机制
- 开发自定义信令处理器,实现消息路由与处理流程
- 扩展客户端功能(新增 WebRTC 能力与 UI 组件)
- 使用插件化扩展点设计原则与最佳实践
- 考虑版本兼容性与向后兼容性
## 项目结构
项目采用前后端分离的模块化组织:
- 服务端Node.js + Express + WebSocket负责信令路由、消息持久化与广播
- 客户端(浏览器端 JS封装 HTTP 与 WebSocket 两类信令通道,驱动 WebRTC PeerConnection
```mermaid
graph TB
subgraph "服务端"
IDX["入口: src/index.ts"]
SRV["HTTP 服务器: src/server.ts"]
WS["WebSocket 信令: src/websocket.ts"]
WSH["WebSocket 处理器: src/class/websockethandler.ts"]
HTH["HTTP 处理器: src/class/httphandler.ts"]
SIG["HTTP 路由: src/signaling.ts"]
end
subgraph "客户端"
CL_SIG["信令封装: client/src/signaling.js"]
CL_PEER["WebRTC 对端: client/src/peer.js"]
end
IDX --> SRV
SRV --> SIG
SRV --> WS
WS --> WSH
SIG --> HTH
CL_SIG --> WS
CL_SIG --> SIG
CL_PEER --> CL_SIG
```
图表来源
- [src/index.ts:13-109](file://src/index.ts#L13-L109)
- [src/server.ts:14-90](file://src/server.ts#L14-L90)
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-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)
- [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)
章节来源
- [src/index.ts:13-109](file://src/index.ts#L13-L109)
- [src/server.ts:14-90](file://src/server.ts#L14-L90)
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-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)
- [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)
## 核心组件
- 信令模型类Offer、Answer、Candidate承载 SDP 与 ICE 候选等数据
- WebSocket 信令WSSignaling 负责连接生命周期与消息分发
- WebSocket 处理器websockethandler 提供连接组管理、广播、消息路由
- HTTP 信令httphandler 提供会话、连接、offer/answer/candidate 的持久化与轮询接口
- HTTP 路由signaling 路由器挂载在 /signaling 下,统一暴露 REST API
- 客户端封装signaling.js 提供 HTTP 与 WebSocket 两种信令通道peer.js 驱动 WebRTC
章节来源
- [src/class/offer.ts:1-11](file://src/class/offer.ts#L1-L11)
- [src/class/answer.ts:1-8](file://src/class/answer.ts#L1-L8)
- [src/class/candidate.ts:1-12](file://src/class/candidate.ts#L1-L12)
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-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)
- [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)
## 架构总览
WebSocket 与 HTTP 两条信令通道并行工作:
- WebSocket低延迟、实时广播、支持 ping/pong 心跳
- HTTP轮询获取历史信令适合弱网或受限环境
```mermaid
sequenceDiagram
participant C as "客户端"
participant WS as "WSSignaling"
participant WH as "WebSocket 处理器"
participant HS as "HTTP 服务器"
participant HH as "HTTP 处理器"
C->>WS : "connect/disconnect/offer/answer/candidate"
WS->>WH : "分发消息类型"
WH-->>C : "广播/单播回执"
C->>HS : "PUT/GET/POST /signaling/*"
HS->>HH : "路由到处理器"
HH-->>C : "返回历史信令/状态"
```
图表来源
- [src/websocket.ts:44-115](file://src/websocket.ts#L44-L115)
- [src/class/websockethandler.ts:76-338](file://src/class/websockethandler.ts#L76-L338)
- [src/server.ts:25-42](file://src/server.ts#L25-L42)
- [src/signaling.ts:6-24](file://src/signaling.ts#L6-L24)
- [src/class/httphandler.ts:398-641](file://src/class/httphandler.ts#L398-L641)
章节来源
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118)
- [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479)
- [src/server.ts:14-90](file://src/server.ts#L14-L90)
- [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25)
- [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800)
## 详细组件分析
### 1) 新增信令消息类型(以 Offer/Answer/Candidate 为例)
- 数据模型
- Offer包含 sdp、datetime、polite 字段
- Answer包含 sdp、datetime
- Candidate包含 candidate、sdpMLineIndex、sdpMid、datetime
- 服务端处理
- WebSocket在 WSSignaling 中解析消息类型并调用 websockethandler 的 onOffer/onAnswer/onCandidate
- HTTP在 httphandler 中维护会话级的 offers/answers/candidates 映射,提供 GET/POST 接口
- 客户端封装
- HTTP 与 WebSocket 两端均提供发送与接收事件,便于上层业务订阅
```mermaid
classDiagram
class Offer {
+string sdp
+number datetime
+boolean polite
}
class Answer {
+string sdp
+number datetime
}
class Candidate {
+string candidate
+number sdpMLineIndex
+string sdpMid
+number datetime
}
class WebSocket_Handler {
+onOffer(ws,msg)
+onAnswer(ws,msg)
+onCandidate(ws,msg)
}
class HTTP_Handler {
+postOffer(req,res)
+postAnswer(req,res)
+postCandidate(req,res)
+getOffer(req,res)
+getAnswer(req,res)
+getCandidate(req,res)
}
WebSocket_Handler --> Offer : "构造/转发"
WebSocket_Handler --> Answer : "构造/转发"
WebSocket_Handler --> Candidate : "构造/转发"
HTTP_Handler --> Offer : "持久化/查询"
HTTP_Handler --> Answer : "持久化/查询"
HTTP_Handler --> Candidate : "持久化/查询"
```
图表来源
- [src/class/offer.ts:1-11](file://src/class/offer.ts#L1-L11)
- [src/class/answer.ts:1-8](file://src/class/answer.ts#L1-L8)
- [src/class/candidate.ts:1-12](file://src/class/candidate.ts#L1-L12)
- [src/class/websockethandler.ts:214-338](file://src/class/websockethandler.ts#L214-L338)
- [src/class/httphandler.ts:398-641](file://src/class/httphandler.ts#L398-L641)
章节来源
- [src/class/offer.ts:1-11](file://src/class/offer.ts#L1-L11)
- [src/class/answer.ts:1-8](file://src/class/answer.ts#L1-L8)
- [src/class/candidate.ts:1-12](file://src/class/candidate.ts#L1-L12)
- [src/class/websockethandler.ts:214-338](file://src/class/websockethandler.ts#L214-L338)
- [src/class/httphandler.ts:398-641](file://src/class/httphandler.ts#L398-L641)
### 2) WebSocketHandler 扩展机制
- 连接组管理host 与 participants 的角色区分,支持私有模式下的多对一/一对一路由
- 广播与单播:根据消息类型与角色进行目标选择
- 心跳与断线:定时心跳检测,超时自动断开并广播离线事件
- 新消息类型接入步骤
1) 在 WSSignaling 的消息分发处增加 case 分支
2) 在 websockethandler 中实现对应处理函数(如 onXxx完成路由与广播
3) 在客户端 signaling.js 中订阅并派发自定义事件
```mermaid
sequenceDiagram
participant WS as "WebSocket"
participant WSH as "websockethandler"
participant P as "参与者"
WS->>WSH : "type='xxx'"
WSH->>WSH : "匹配处理函数"
WSH->>P : "广播/单播消息"
P-->>WSH : "回执/确认"
```
图表来源
- [src/websocket.ts:76-113](file://src/websocket.ts#L76-L113)
- [src/class/websockethandler.ts:97-137](file://src/class/websockethandler.ts#L97-L137)
- [src/class/websockethandler.ts:214-338](file://src/class/websockethandler.ts#L214-L338)
章节来源
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118)
- [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479)
### 3) HttpHandler 扩展机制
- 会话与连接:通过 session-id 维持会话上下文支持连接对connectionPair在私有模式下建立双向关系
- 消息持久化offers/answers/candidates 以会话+连接维度缓存,支持 fromtime 过滤
- 轮询接口:提供 /signaling、/signaling/offer、/signaling/answer、/signaling/candidate 的 GET/POST
- 新消息类型接入步骤
1) 在 httphandler 中新增 postXxx 与 getXxx 方法,维护内部映射
2) 在 signaling 路由中注册对应路由
3) 在客户端 signaling.js 中补充发送与接收逻辑
```mermaid
flowchart TD
Start(["HTTP 请求进入"]) --> CheckSession["校验 session-id"]
CheckSession --> Route{"路由到哪?"}
Route --> |GET /signaling| GetAll["合并并排序历史消息"]
Route --> |GET /signaling/offer| GetOffer["按会话/时间过滤 offer"]
Route --> |GET /signaling/answer| GetAnswer["按会话/时间过滤 answer"]
Route --> |GET /signaling/candidate| GetCandidate["按会话/时间过滤 candidate"]
Route --> |POST /signaling/offer| PostOffer["写入 offer 映射"]
Route --> |POST /signaling/answer| PostAnswer["写入 answer 映射"]
Route --> |POST /signaling/candidate| PostCandidate["写入 candidate 映射"]
GetAll --> End(["返回 JSON"])
GetOffer --> End
GetAnswer --> End
GetCandidate --> End
PostOffer --> End
PostAnswer --> End
PostCandidate --> End
```
图表来源
- [src/class/httphandler.ts:128-145](file://src/class/httphandler.ts#L128-L145)
- [src/class/httphandler.ts:398-641](file://src/class/httphandler.ts#L398-L641)
- [src/signaling.ts:6-24](file://src/signaling.ts#L6-L24)
章节来源
- [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800)
- [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25)
### 4) 自定义信令处理器开发指南
- 设计原则
- 单一职责:每个处理器只负责一类消息或一类资源
- 可组合:通过中间件/装饰器模式复用鉴权、日志、限流
- 可替换:对外暴露一致的 API内部可替换实现
- 消息路由与处理流程
- WebSocket在 WSSignaling 的 switch 分支中新增 case调用处理器对应方法
- HTTP在 signaling 路由中注册新路由,处理器中实现鉴权与数据持久化
- 客户端集成
- 在 signaling.js 中新增发送与接收事件,确保与服务端消息结构一致
- 在 peer.js 或业务层订阅事件并驱动 WebRTC
```mermaid
sequenceDiagram
participant App as "应用层"
participant WS as "WSSignaling"
participant WH as "自定义处理器"
participant HH as "自定义 HTTP 处理器"
participant CL as "客户端"
App->>WS : "发送自定义消息"
WS->>WH : "分发到自定义处理器"
WH-->>CL : "广播/回执"
App->>HH : "HTTP 请求"
HH-->>CL : "返回处理结果"
CL-->>App : "事件回调"
```
图表来源
- [src/websocket.ts:76-113](file://src/websocket.ts#L76-L113)
- [src/signaling.ts:6-24](file://src/signaling.ts#L6-L24)
- [client/src/signaling.js:152-292](file://client/src/signaling.js#L152-L292)
章节来源
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118)
- [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25)
- [client/src/signaling.js:1-292](file://client/src/signaling.js#L1-L292)
### 5) 扩展客户端功能WebRTC 与 UI 组件)
- 新增 WebRTC 能力
- 在 peer.js 中扩展事件(如 onCustomMessage并在 signaling.js 中订阅
- 如需数据通道,参考 createDataChannel 与 ondatachannel 的使用模式
- UI 组件
- 基于现有 signaling.js 的事件模型,新增 DOM 事件监听与渲染逻辑
- 保持与现有连接/断开/offer/answer/candidate 事件的兼容
章节来源
- [client/src/peer.js:1-188](file://client/src/peer.js#L1-L188)
- [client/src/signaling.js:1-292](file://client/src/signaling.js#L1-L292)
### 6) 插件系统与扩展点设计原则
- 扩展点
- WebSocket 消息分发:在 WSSignaling 的 switch 中新增 case
- HTTP 路由:在 signaling 路由中新增子路由
- 处理器内部:在 websockethandler/httphandler 中新增处理函数
- 设计原则
- 向后兼容:新增字段建议可选,避免破坏既有消息结构
- 版本化:通过消息中的 version 字段或路由版本号区分
- 强约束:严格校验必填字段,失败时返回明确错误码
- 可观测:为新消息类型增加日志与指标埋点
章节来源
- [src/websocket.ts:76-113](file://src/websocket.ts#L76-L113)
- [src/signaling.ts:6-24](file://src/signaling.ts#L6-L24)
- [src/class/websockethandler.ts:76-338](file://src/class/websockethandler.ts#L76-L338)
- [src/class/httphandler.ts:398-641](file://src/class/httphandler.ts#L398-L641)
### 7) 实际扩展示例与最佳实践
- 示例:新增“自定义消息”类型
- 服务端
- 在 WSSignaling 的 switch 中新增 case"custom"
- 在 websockethandler 中实现 onCustom完成路由与广播
- 在 httphandler 中新增 postCustom/getCustom维护映射
- 在 signaling 路由中注册 /signaling/custom
- 客户端
- 在 signaling.js 中新增 sendCustom 与订阅 "custom" 事件
- 最佳实践
- 消息结构最小化:仅包含必要字段
- 错误处理:对缺失字段与非法值返回 4xx/5xx 并记录日志
- 幂等性:对重复消息进行去重(基于时间戳或唯一 ID
- 性能:批量消息合并、异步处理、限流与背压
章节来源
- [src/websocket.ts:76-113](file://src/websocket.ts#L76-L113)
- [src/class/websockethandler.ts:214-338](file://src/class/websockethandler.ts#L214-L338)
- [src/class/httphandler.ts:398-641](file://src/class/httphandler.ts#L398-L641)
- [src/signaling.ts:6-24](file://src/signaling.ts#L6-L24)
- [client/src/signaling.js:1-292](file://client/src/signaling.js#L1-L292)
## 依赖分析
- 服务端依赖
- ExpressHTTP 服务器与路由
- wsWebSocket 服务器
- morganHTTP 日志
- uuid会话 ID 生成
- 客户端依赖
- 浏览器原生 fetch/WebSocket
- Jest测试
```mermaid
graph LR
PKG["服务端 package.json"] --> EXP["express"]
PKG --> WS["ws"]
PKG --> MORGAN["morgan"]
PKG --> UUID["uuid"]
CLPKG["客户端 package.json"] --> JEST["jest"]
CLPKG --> ESLINT["eslint"]
```
图表来源
- [package.json:14-27](file://package.json#L14-L27)
- [client/package.json:9-18](file://client/package.json#L9-L18)
章节来源
- [package.json:1-60](file://package.json#L1-L60)
- [client/package.json:1-19](file://client/package.json#L1-L19)
## 性能考量
- WebSocket
- 心跳间隔与超时阈值可调,避免频繁断线
- 大消息拆分与压缩,减少带宽占用
- HTTP
- fromtime 参数配合增量拉取,降低响应体积
- 合理设置轮询间隔,平衡实时性与资源消耗
- 通用
- 缓存热点数据(如最近 N 条 candidate
- 异步处理耗时操作(如持久化)
## 故障排查指南
- WebSocket 无法连接
- 检查 WSSignaling 的连接事件与日志
- 确认客户端 URL 与协议ws/wss
- 消息未到达
- 核对 websockethandler 的广播逻辑与角色判断
- 确认客户端事件监听是否正确
- HTTP 会话异常
- 检查 session-id 请求头与会话超时清理
- 使用 getAll 接口核对历史消息
- 单元测试参考
- 使用 websockethandler.test.ts 验证消息路由与广播行为
章节来源
- [src/websocket.ts:27-38](file://src/websocket.ts#L27-L38)
- [src/class/websockethandler.ts:97-137](file://src/class/websockethandler.ts#L97-L137)
- [src/class/httphandler.ts:218-232](file://src/class/httphandler.ts#L218-L232)
- [test/websockethandler.test.ts:1-191](file://test/websockethandler.test.ts#L1-L191)
## 结论
通过明确的扩展点与清晰的处理流程,项目允许以最小改动安全地引入新的信令消息类型与客户端能力。遵循向后兼容、可观测与可测试的原则,可确保扩展的稳定性与演进速度。
## 附录
- 版本与兼容性
- 服务端与客户端版本号3.1.0
- 建议在新增字段时保留默认值,避免破坏旧客户端解析
- 对于重大变更,建议引入版本字段或路由版本号
章节来源
- [package.json:1-60](file://package.json#L1-L60)
- [client/package.json:1-19](file://client/package.json#L1-L19)