mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-12-24 13:48:04 +08:00
308 lines
9.8 KiB
Markdown
308 lines
9.8 KiB
Markdown
# 测试插件
|
||
|
||
测试插件是 Monibuca v5 的综合测试框架,为各种流媒体协议和媒体处理场景提供自动化测试能力。它使开发者能够通过可配置的测试用例来验证流媒体功能、性能和可靠性。
|
||
|
||
## 概述
|
||
|
||
测试插件作为 Monibuca 流媒体能力的质量保证工具,提供:
|
||
|
||
- **自动化测试用例**:为常见流媒体工作流预配置测试场景
|
||
- **多协议支持**:支持 RTMP、RTSP、SRT、WebRTC、HLS、MP4、FLV 和 PS 协议的测试
|
||
- **压力测试**:通过可配置的并发推拉流操作进行性能测试
|
||
- **实时监控**:通过服务器发送事件(SSE)提供实时状态更新
|
||
- **灵活的任务系统**:可扩展的任务框架,支持自定义测试场景
|
||
|
||
## 架构设计
|
||
|
||
### 核心组件
|
||
|
||
1. **TestPlugin**:主插件控制器,管理测试用例和压力测试
|
||
2. **TestCase**:具有可配置任务和参数的单个测试场景
|
||
3. **TestTaskFactory**:用于创建不同类型测试任务的工厂模式
|
||
4. **任务类型**:针对不同操作的专业化任务(推流、拉流、截图、录制、读取)
|
||
|
||
### 任务系统设计
|
||
|
||
插件使用复杂的任务编排系统:
|
||
|
||
```go
|
||
type TestTaskConfig struct {
|
||
Action string `json:"action"` // 任务类型:push, pull, snapshot, write, read
|
||
Delay time.Duration `json:"delay"` // 任务执行前的延迟
|
||
Format string `json:"format"` // 协议/格式:rtmp, rtsp, srt 等
|
||
ServerAddr string `json:"serverAddr"` // 目标服务器地址
|
||
Input string `json:"input"` // 输入源(文件、URL 等)
|
||
StreamPath string `json:"streamPath"` // 流标识符
|
||
}
|
||
```
|
||
|
||
### 任务类型详解
|
||
|
||
#### 1. 推流任务(`AcceptPushTask`)
|
||
- **目的**:模拟向服务器推送媒体流
|
||
- **实现**:使用 FFmpeg 从文件或实时源推送媒体
|
||
- **支持格式**:RTMP、RTSP、SRT、WebRTC、PS
|
||
- **设计巧思**:利用 FFmpeg 强大的流媒体能力,同时通过进程管理保持控制
|
||
|
||
#### 2. 截图任务(`SnapshotTask`)
|
||
- **目的**:从流中捕获帧以验证内容质量
|
||
- **实现**:两种模式:
|
||
- 直接从流 URL 进行 FFmpeg 捕获
|
||
- 内部流订阅与 AnnexB 格式处理
|
||
- **设计巧思**:双重方法允许测试外部可访问性和内部流处理
|
||
|
||
#### 3. 录制任务(`WriteRemoteTask`)
|
||
- **目的**:将流录制为各种格式
|
||
- **实现**:与 Monibuca 的录制插件集成
|
||
- **支持格式**:MP4、FLV、HLS、PS
|
||
- **设计巧思**:重用现有录制基础设施以确保一致性
|
||
|
||
#### 4. 读取任务(`ReadRemoteTask`)
|
||
- **目的**:从各种源拉取流
|
||
- **实现**:使用 Monibuca 的拉流插件
|
||
- **支持格式**:MP4、FLV、HLS、RTMP、RTSP、SRT、WebRTC、AnnexB
|
||
- **设计巧思**:为不同拉流器实现提供统一接口
|
||
|
||
## 关键设计模式
|
||
|
||
### 1. 工厂模式
|
||
`TestTaskFactory` 使用注册表模式动态创建任务:
|
||
|
||
```go
|
||
func (f *TestTaskFactory) Register(action string, taskCreator func(*TestCase, TestTaskConfig) task.ITask) {
|
||
f.tasks[action] = taskCreator
|
||
}
|
||
```
|
||
|
||
这允许轻松扩展新任务类型而无需修改核心代码。
|
||
|
||
### 2. 基于反射的任务编排
|
||
测试用例执行使用 Go 的反射 API 进行动态任务调度:
|
||
|
||
```go
|
||
subTaskSelect := []reflect.SelectCase{
|
||
{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(time.After(ts.Timeout))},
|
||
{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ts.Done())},
|
||
}
|
||
```
|
||
|
||
这实现了复杂的时间控制和并行任务执行。
|
||
|
||
### 3. 实时状态更新
|
||
插件实现服务器发送事件(SSE)进行实时监控:
|
||
|
||
```go
|
||
func (p *TestPlugin) GetTestCaseSSE(w http.ResponseWriter, r *http.Request) {
|
||
util.NewSSE(w, r.Context(), func(sse *util.SSE) {
|
||
// 实时状态广播
|
||
})
|
||
}
|
||
```
|
||
|
||
### 4. 压力测试架构
|
||
压力测试系统维护活跃推拉流操作的集合:
|
||
|
||
```go
|
||
type TestPlugin struct {
|
||
pushers util.Collection[string, *m7s.PushJob]
|
||
pullers util.Collection[string, *m7s.PullJob]
|
||
}
|
||
```
|
||
|
||
这允许动态扩展和管理并发操作。
|
||
|
||
## 配置说明
|
||
|
||
### 测试用例配置
|
||
|
||
测试用例以 YAML 格式定义,结构如下:
|
||
|
||
```yaml
|
||
cases:
|
||
test_name:
|
||
description: "测试描述"
|
||
videoCodec: "h264"
|
||
audioCodec: "aac"
|
||
videoOnly: false
|
||
audioOnly: false
|
||
timeout: "30s"
|
||
tasks:
|
||
- action: push
|
||
format: rtmp
|
||
delay: 0s
|
||
- action: snapshot
|
||
format: rtmp
|
||
delay: 5s
|
||
```
|
||
|
||
### 预配置测试用例
|
||
|
||
插件包含全面的测试场景:
|
||
|
||
- **协议交叉测试**:RTMP↔RTSP、RTMP↔SRT、RTSP↔SRT
|
||
- **文件格式测试**:MP4、FLV、HLS 读取和录制
|
||
- **高级功能**:PS 封装、AnnexB 处理、WebRTC 测试
|
||
|
||
## API 接口
|
||
|
||
### REST API
|
||
- `GET /test/api/cases` - 列出测试用例
|
||
- `POST /test/api/cases/execute` - 执行测试用例
|
||
- `GET /test/api/stress/count` - 获取压力测试计数
|
||
- `POST /test/api/stress/push/{protocol}/{count}` - 开始推流压力测试
|
||
- `POST /test/api/stress/pull/{protocol}/{count}` - 开始拉流压力测试
|
||
|
||
### 服务器发送事件
|
||
- `GET /sse/cases` - 实时测试用例状态更新
|
||
|
||
### gRPC API
|
||
完整的 gRPC 服务定义在 `pb/test.proto` 中,包含相应的 HTTP 网关端点。
|
||
|
||
## 使用示例
|
||
|
||
### 基本测试执行
|
||
```bash
|
||
# 执行特定测试用例
|
||
curl -X POST http://localhost:8080/test/api/cases/execute \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"names": ["rtmp2rtmp"]}'
|
||
```
|
||
|
||
### 压力测试
|
||
```bash
|
||
# 启动 10 个并发 RTMP 推流
|
||
curl -X POST http://localhost:8080/test/api/stress/push/rtmp/10 \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"streamPath": "stress_test",
|
||
"remoteURL": "rtmp://localhost/live/%d"
|
||
}'
|
||
```
|
||
|
||
### 实时监控
|
||
```javascript
|
||
// 监控测试用例状态
|
||
const eventSource = new EventSource('/sse/cases');
|
||
eventSource.onmessage = function(event) {
|
||
const testCases = JSON.parse(event.data);
|
||
// 使用测试状态更新 UI
|
||
};
|
||
```
|
||
|
||
## 高级功能
|
||
|
||
### 1. 动态流路径生成
|
||
插件自动为并行测试执行生成唯一流路径:
|
||
|
||
```go
|
||
if taskConfig.StreamPath == "" {
|
||
taskConfig.StreamPath = fmt.Sprintf("test/%d", ts.ID)
|
||
}
|
||
```
|
||
|
||
### 2. 智能输入处理
|
||
支持基于文件和基于 URL 的输入,具有自动路径解析:
|
||
|
||
```go
|
||
if taskConfig.Input != "" && !strings.Contains(taskConfig.Input, ".") {
|
||
taskConfig.Input = fmt.Sprintf("%s/%d", taskConfig.Input, ts.ID)
|
||
}
|
||
```
|
||
|
||
### 3. 综合日志记录
|
||
每个测试用例维护带时间戳的详细日志:
|
||
|
||
```go
|
||
func (ts *TestCase) Write(buf []byte) (int, error) {
|
||
ts.Logs += time.Now().Format("2006-01-02 15:04:05") + " " + string(buf) + "\n"
|
||
return len(buf), nil
|
||
}
|
||
```
|
||
|
||
## 与 Monibuca 生态系统的集成
|
||
|
||
测试插件与 Monibuca 的插件架构无缝集成:
|
||
|
||
- **插件注册**:使用 `m7s.InstallPlugin` 进行自动发现
|
||
- **配置管理**:利用 Monibuca 的配置系统
|
||
- **任务框架**:基于 Monibuca 的任务管理系统构建
|
||
- **流管理**:与发布者/订阅者模型集成
|
||
|
||
## 性能考虑
|
||
|
||
### 内存管理
|
||
- 使用 `util.Memory` 进行高效的缓冲区管理
|
||
- 为临时文件和进程实现适当的清理
|
||
- 利用 Go 的垃圾收集器进行自动内存管理
|
||
|
||
### 并发性
|
||
- 使用 Monibuca 的 `Call` 方法进行线程安全操作
|
||
- 为压力测试进行高效的集合管理
|
||
- 非阻塞 SSE 实现
|
||
|
||
### 资源清理
|
||
- 任务完成时自动终止进程
|
||
- 录制测试后清理临时文件
|
||
- 网络操作的适当连接管理
|
||
|
||
## 可扩展性
|
||
|
||
插件设计便于扩展:
|
||
|
||
1. **新任务类型**:向工厂注册新的任务创建器
|
||
2. **自定义协议**:添加对新流媒体协议的支持
|
||
3. **高级指标**:扩展监控和报告功能
|
||
4. **集成测试**:创建复杂的多步骤测试场景
|
||
|
||
## 最佳实践
|
||
|
||
1. **测试隔离**:每个测试用例使用唯一的流路径运行
|
||
2. **超时管理**:为不同场景配置适当的超时
|
||
3. **资源监控**:在压力测试期间监控系统资源
|
||
4. **日志分析**:使用详细日志进行调试和性能分析
|
||
5. **增量测试**:在复杂场景之前从简单用例开始
|
||
|
||
## 故障排除
|
||
|
||
### 常见问题
|
||
|
||
1. **找不到 FFmpeg**:确保 FFmpeg 已安装并在 PATH 中
|
||
2. **端口冲突**:在压力测试中检查端口可用性
|
||
3. **文件权限**:确保录制测试的写入权限
|
||
4. **网络连接**:验证远程流测试的网络访问
|
||
|
||
### 调试模式
|
||
通过在 Monibuca 配置中设置适当的日志级别来启用详细日志记录。
|
||
|
||
## 设计巧思总结
|
||
|
||
### 1. 任务工厂模式
|
||
通过注册表模式实现任务的动态创建,使得添加新任务类型变得非常简单,无需修改核心代码。
|
||
|
||
### 2. 反射驱动的任务调度
|
||
使用 Go 的反射 API 实现复杂的任务编排,支持动态延迟和并行执行,提供了极大的灵活性。
|
||
|
||
### 3. 双重截图机制
|
||
截图任务支持两种模式:外部 FFmpeg 捕获和内部流订阅,既测试了外部可访问性,又验证了内部流处理能力。
|
||
|
||
### 4. 智能资源管理
|
||
通过 `util.Collection` 管理并发操作,支持动态扩展和收缩,实现了高效的压力测试。
|
||
|
||
### 5. 实时状态同步
|
||
使用 SSE 技术实现实时状态更新,为测试监控提供了良好的用户体验。
|
||
|
||
### 6. 流路径隔离
|
||
自动生成唯一的流路径,确保并行测试之间不会相互干扰,提高了测试的可靠性。
|
||
|
||
## 未来增强
|
||
|
||
- **可视化测试报告**:基于 HTML 的测试结果可视化
|
||
- **性能指标**:详细的性能分析和报告
|
||
- **CI/CD 集成**:在持续集成管道中的自动化测试
|
||
- **自定义断言**:用户定义的测试用例验证规则
|
||
- **分布式测试**:多节点测试能力
|
||
|
||
---
|
||
|
||
测试插件代表了流媒体测试的复杂方法,结合了灵活性、性能和易用性,以确保 Monibuca 流媒体能力的可靠性。通过其精心设计的架构和丰富的功能集,它为开发者提供了一个强大的工具来验证和优化流媒体系统。
|