Files
monibuca/plugin/test/README_CN.md
2025-09-24 12:14:49 +08:00

9.8 KiB
Raw Blame History

测试插件

测试插件是 Monibuca v5 的综合测试框架,为各种流媒体协议和媒体处理场景提供自动化测试能力。它使开发者能够通过可配置的测试用例来验证流媒体功能、性能和可靠性。

概述

测试插件作为 Monibuca 流媒体能力的质量保证工具,提供:

  • 自动化测试用例:为常见流媒体工作流预配置测试场景
  • 多协议支持:支持 RTMP、RTSP、SRT、WebRTC、HLS、MP4、FLV 和 PS 协议的测试
  • 压力测试:通过可配置的并发推拉流操作进行性能测试
  • 实时监控通过服务器发送事件SSE提供实时状态更新
  • 灵活的任务系统:可扩展的任务框架,支持自定义测试场景

架构设计

核心组件

  1. TestPlugin:主插件控制器,管理测试用例和压力测试
  2. TestCase:具有可配置任务和参数的单个测试场景
  3. TestTaskFactory:用于创建不同类型测试任务的工厂模式
  4. 任务类型:针对不同操作的专业化任务(推流、拉流、截图、录制、读取)

任务系统设计

插件使用复杂的任务编排系统:

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 使用注册表模式动态创建任务:

func (f *TestTaskFactory) Register(action string, taskCreator func(*TestCase, TestTaskConfig) task.ITask) {
    f.tasks[action] = taskCreator
}

这允许轻松扩展新任务类型而无需修改核心代码。

2. 基于反射的任务编排

测试用例执行使用 Go 的反射 API 进行动态任务调度:

subTaskSelect := []reflect.SelectCase{
    {Dir: reflect.SelectRecv, Chan: reflect.ValueOf(time.After(ts.Timeout))},
    {Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ts.Done())},
}

这实现了复杂的时间控制和并行任务执行。

3. 实时状态更新

插件实现服务器发送事件SSE进行实时监控

func (p *TestPlugin) GetTestCaseSSE(w http.ResponseWriter, r *http.Request) {
    util.NewSSE(w, r.Context(), func(sse *util.SSE) {
        // 实时状态广播
    })
}

4. 压力测试架构

压力测试系统维护活跃推拉流操作的集合:

type TestPlugin struct {
    pushers util.Collection[string, *m7s.PushJob]
    pullers util.Collection[string, *m7s.PullJob]
}

这允许动态扩展和管理并发操作。

配置说明

测试用例配置

测试用例以 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 网关端点。

使用示例

基本测试执行

# 执行特定测试用例
curl -X POST http://localhost:8080/test/api/cases/execute \
  -H "Content-Type: application/json" \
  -d '{"names": ["rtmp2rtmp"]}'

压力测试

# 启动 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"
  }'

实时监控

// 监控测试用例状态
const eventSource = new EventSource('/sse/cases');
eventSource.onmessage = function(event) {
    const testCases = JSON.parse(event.data);
    // 使用测试状态更新 UI
};

高级功能

1. 动态流路径生成

插件自动为并行测试执行生成唯一流路径:

if taskConfig.StreamPath == "" {
    taskConfig.StreamPath = fmt.Sprintf("test/%d", ts.ID)
}

2. 智能输入处理

支持基于文件和基于 URL 的输入,具有自动路径解析:

if taskConfig.Input != "" && !strings.Contains(taskConfig.Input, ".") {
    taskConfig.Input = fmt.Sprintf("%s/%d", taskConfig.Input, ts.ID)
}

3. 综合日志记录

每个测试用例维护带时间戳的详细日志:

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 流媒体能力的可靠性。通过其精心设计的架构和丰富的功能集,它为开发者提供了一个强大的工具来验证和优化流媒体系统。