repair-agent 134ccb70f3
All checks were successful
Build and Deploy Backend / build-and-deploy (push) Successful in 5m41s
fix 音频并发优化
2026-03-03 17:21:46 +08:00

3.9 KiB
Raw Permalink Blame History

hw_service_go 并发压力测试报告

测试时间2026-03-03 测试目标:wss://qiyuan-rtc-api.airlabs.art/xiaozhi/v1/ Pod 配置:单 PodCPU 100m500mlimitsMemory 128Mi512Milimitsreplicas: 1


一、测试环境

项目 配置
服务 hw_service_goWebSocket + Opus 音频推送)
部署 K8s 单 Pod1 副本
CPU limits 500m0.5 核)
Memory limits 512Mi
硬编码连接上限 500
测试工具 Go 压测工具(test/stress/main.go
测试客户端 macOS从公网连接线上服务

二、测试结果

2.1 连接容量测试(空闲连接)

go run main.go -url wss://..../xiaozhi/v1/ -conns 200 -stories 0 -duration 30s
指标 结果
目标连接 200
成功连接 200
握手成功 200
错误 0

结论200 个空闲连接毫无压力,内存不是瓶颈。

2.2 并发播放压力测试

每个"活跃故事"会触发Django API 查询 → MP3 下载 → ffmpeg 转码 → Opus 编码 → WebSocket 推帧。

并发故事数 总连接 首帧延迟 帧数/故事 错误 状态
2 10 2.0s 796 0 轻松
5 10 4.5s 796 0 正常
10 20 8.7s 796 0 吃力但稳
20 30 17.4s 796 0 极限

2.3 关键发现

  1. 帧数始终稳定 796/故事 — 音频完整交付,零丢帧,服务可靠性极高
  2. 首帧延迟线性增长 — 约 0.85s/并发,纯 CPU 瓶颈(多个 ffmpeg 进程争抢 0.5 核)
  3. Pod 未触发 OOMKill — 512Mi 内存对 20 并发播放也够用
  4. 全程零错误 — 无连接断开、无握手失败、无帧丢失

三、瓶颈分析

单个故事播放的资源消耗链路:

Django API (GET) → MP3 下载 (OSS) → ffmpeg 转码 (CPU密集) → Opus 编码 → WebSocket 推帧
                                      ↑
                                  主要瓶颈
                            每个并发故事启动一个 ffmpeg 子进程
                            多个 ffmpeg 共享 0.5 核 CPU
资源 是否瓶颈 说明
CPU ffmpeg 转码是 CPU 密集型0.5 核被多个 ffmpeg 进程分时使用
内存 20 并发播放未触发 OOM512Mi 充足
网络 Opus 帧约 4-7 KB/s/连接,带宽远未饱和
连接数 空闲连接 200+ 无压力,硬上限 500

四、容量结论

当前单 Pod0.5 核 CPU, 512Mi, 1 副本)

指标 数值
空闲连接上限 200+(轻松)
并发播放(体验好,首帧 < 5s ~5 个
并发播放(可接受,首帧 < 10s ~10 个
并发播放(极限,首帧 ~17s ~20 个
瓶颈资源 CPUffmpeg 转码)

五、扩容建议

方案 变更 预估并发播放(首帧 < 10s 成本
提 CPU limits 500m → 1000m ~20 个
加副本 replicas 1 → 2 ~10 个(负载均衡)
两者都做 1000m CPU + 2 副本 ~40 个
垂直扩容 2000m CPU + 1Gi 内存 ~40 个

推荐方案replicas: 2 + CPU limits: 1000m兼顾高可用与并发能力。


六、测试命令参考

cd hw_service_go/test/stress

# 空闲连接容量
go run main.go -url wss://TARGET/xiaozhi/v1/ -conns 200 -stories 0 -duration 30s

# 并发播放(逐步加压)
go run main.go -url wss://TARGET/xiaozhi/v1/ -conns 10 -stories 2 -duration 60s
go run main.go -url wss://TARGET/xiaozhi/v1/ -conns 10 -stories 5 -duration 60s
go run main.go -url wss://TARGET/xiaozhi/v1/ -conns 20 -stories 10 -duration 90s
go run main.go -url wss://TARGET/xiaozhi/v1/ -conns 30 -stories 20 -duration 120s