# hw_service_go 并发压力测试报告

> 测试时间：2026-03-03
> 测试目标：`wss://qiyuan-rtc-api.airlabs.art/xiaozhi/v1/`
> Pod 配置：单 Pod，CPU 100m~500m（limits），Memory 128Mi~512Mi（limits），replicas: 1

---

## 一、测试环境

| 项目 | 配置 |
|------|------|
| 服务 | hw_service_go（WebSocket + Opus 音频推送） |
| 部署 | K8s 单 Pod，1 副本 |
| CPU limits | 500m（0.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 并发播放未触发 OOM，512Mi 充足 |
| 网络 | 否 | Opus 帧约 4-7 KB/s/连接，带宽远未饱和 |
| 连接数 | 否 | 空闲连接 200+ 无压力，硬上限 500 |

---

## 四、容量结论

### 当前单 Pod（0.5 核 CPU, 512Mi, 1 副本）

| 指标 | 数值 |
|------|------|
| 空闲连接上限 | **200+**（轻松） |
| 并发播放（体验好，首帧 < 5s） | **~5 个** |
| 并发播放（可接受，首帧 < 10s） | **~10 个** |
| 并发播放（极限，首帧 ~17s） | **~20 个** |
| 瓶颈资源 | CPU（ffmpeg 转码） |

---

## 五、扩容建议

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

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

---

## 六、测试命令参考

```bash
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
```
