Files
1818web-hoduan/RUNNINGHUB_CONCURRENCY_ANALYSIS.md
2025-11-14 17:41:15 +08:00

581 lines
15 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

# RunningHub 并发能力分析与优化方案
**版本:** v2.1.0
**更新时间:** 2025-10-20
**分析人员:** AI架构团队
---
## 📊 一、RunningHub API并发能力评估
### 1.1 API架构分析
RunningHub采用**异步任务处理模式**,这种架构天然支持高并发:
```
客户端请求 → 提交任务(秒级响应) → 返回TaskID → 客户端轮询 → 获取结果
```
**优势:**
- ✅ 提交接口无需等待任务完成,可快速响应
- ✅ 任务在后台队列中处理不占用HTTP连接
- ✅ 理论上可同时提交大量任务
---
### 1.2 并发限制因素
#### A. API Key限制未知需测试
RunningHub未公开以下限制
- ❓ 每秒最大请求数QPS
- ❓ 每分钟最大请求数QPM
- ❓ 单个API Key的并发任务数
- ❓ 账户级别的任务队列限制
**建议测试方案:**
```bash
# 逐步压力测试
1. 同时提交10个任务 → 观察响应
2. 同时提交50个任务 → 观察是否限流
3. 同时提交100个任务 → 找到阈值
```
#### B. 任务处理能力
根据API文档分析
- **文生视频10秒** 预计处理时间 2-5分钟
- **图生视频10秒** 预计处理时间 2-5分钟
- **高清视频:** 预计处理时间 5-10分钟
**并发处理能力估算:**
假设RunningHub后台有100个GPU实例平均处理时间3分钟
```
理论最大并发 = 100个GPU × (60秒 / 3分钟) = 约2000个任务/小时
```
#### C. 网络带宽限制
- **请求体大小:**
- 文生视频:~2KBprompt + 配置)
- 图生视频:~10KB-500KB包含图片URL或Base64
- **响应体大小:**
- 提交响应:~500B
- 状态查询:~300B
- 结果获取:~1KB只返回URL
**预计带宽需求100并发**
```
上传100 × 500KB = 50MB
下载轮询10次/任务100 × 10 × 1KB = 1MB
总计:~51MB一次性峰值
```
---
## 🔧 二、当前系统并发配置
### 2.1 系统参数
```yaml
# application.yml
ai:
providers:
runninghub:
polling-interval: 10000 # 轮询间隔 10秒已优化
max-polling-times: 60 # 最大轮询60次 = 10分钟
queue:
max-concurrent: 50 # 每个模型最大并发50个
```
### 2.2 并发能力计算
#### A. 系统级并发
**RunningHub模型数量** 12个
```
rh_sora2_text_portrait (文生视频-竖屏)
rh_sora2_text_landscape (文生视频-横屏)
rh_sora2_text_portrait_hd (文生视频-高清竖屏)
rh_sora2_text_landscape_hd (文生视频-高清横屏)
rh_sora2_text_portrait_15s (文生视频-竖屏15秒
rh_sora2_text_landscape_15s (文生视频-横屏15秒
rh_sora2_img_portrait (图生视频-竖屏)
rh_sora2_img_landscape (图生视频-横屏)
rh_sora2_img_portrait_hd (图生视频-高清竖屏)
rh_sora2_img_landscape_hd (图生视频-高清横屏)
rh_sora2_img_portrait_15s (图生视频-竖屏15秒
rh_sora2_img_landscape_15s (图生视频-横屏15秒
```
**理论最大并发:**
```
12个模型 × 50个/模型 = 600个并发任务
```
**但实际上:**
- RunningHub任务不走我们的队列系统直接提交
- 只受RunningHub API限制不受我们的max-concurrent限制
**实际并发能力:** **无限制**取决于RunningHub服务端
#### B. 轮询调度器负载
```java
@Scheduled(fixedRateString = "${ai.providers.runninghub.polling-interval:10000}")
public void pollRunningHubTasks() {
// 查询所有processing状态的RunningHub任务
List<AiTask> processingTasks = aiTaskMapper.findProcessingTasksByProvider("runninghub");
// 每10秒轮询一次
for (AiTask task : processingTasks) {
// 查询状态 → 更新数据库 → 发送WebSocket通知
}
}
```
**轮询负载分析10秒间隔**
| 并发任务数 | 每次轮询耗时 | CPU使用率 | 网络流量/分钟 |
|-----------|------------|----------|--------------|
| 10 | ~1秒 | <5% | ~180KB |
| 50 | ~5秒 | ~10% | ~900KB |
| 100 | ~10秒 | ~20% | ~1.8MB |
| 200 | ~20秒 | ~40% | ~3.6MB |
| 500 | ~50秒 | ~80% | ~9MB |
**安全阈值:** 建议不超过**200个并发任务**否则轮询调度器可能积压
---
## ⚠️ 三、潜在风险与瓶颈
### 3.1 轮询调度器阻塞
**问题:** 如果并发任务过多单次轮询时间超过10秒会导致任务堆积
**示例:**
```
T0: 开始轮询200个任务预计20秒
T10: 第二次调度触发,但上一次还没结束 → 跳过或阻塞
T20: 第一次轮询完成
T30: 第三次调度触发
```
**解决方案:**
1. 使用 `@Scheduled(fixedDelay = 10000)` 替代 `fixedRate`
2. 增加线程池并发查询状态
### 3.2 数据库连接池耗尽
**当前连接池配置(默认):** HikariCP 默认10个连接
**风险:**
```
200个并发任务 × 每个任务3次数据库操作查询+更新+日志) = 600次DB操作/10秒
```
**解决方案:**
```yaml
spring:
datasource:
hikari:
maximum-pool-size: 50 # 增加连接池大小
minimum-idle: 10
connection-timeout: 30000
```
### 3.3 WebSocket连接数
**问题:** 每个在线用户需要一个WebSocket连接来接收实时通知
**并发用户数 vs WebSocket连接**
```
100个并发用户 = 100个WebSocket连接
500个并发用户 = 500个WebSocket连接
```
**Tomcat默认限制** 200个线程
**解决方案:**
```yaml
server:
tomcat:
threads:
max: 500 # 增加最大线程数
min-spare: 50
```
---
## 🚀 四、并发优化方案
### 方案A保守配置推荐用于初期
**目标:** 稳定性优先支持 **100个并发任务**
```yaml
ai:
providers:
runninghub:
polling-interval: 10000 # 10秒轮询
max-polling-times: 60
spring:
datasource:
hikari:
maximum-pool-size: 30
minimum-idle: 10
server:
tomcat:
threads:
max: 300
min-spare: 50
```
**预期性能:**
- 轮询时间~10秒/
- CPU使用率<20%
- 内存占用<2GB
- 网络带宽~2MB/分钟
---
### 方案B高并发配置成熟期
**目标:** 性能优先支持 **500个并发任务**
```yaml
ai:
providers:
runninghub:
polling-interval: 15000 # 15秒轮询减少频率
max-polling-times: 40 # 最大轮询40次 = 10分钟
batch-size: 50 # 分批查询每批50个
spring:
datasource:
hikari:
maximum-pool-size: 100
minimum-idle: 20
server:
tomcat:
threads:
max: 1000
min-spare: 100
# 异步线程池配置
task:
execution:
pool:
core-size: 50
max-size: 200
queue-capacity: 500
```
**优化代码(分批轮询):**
```java
@Scheduled(fixedDelay = 15000)
public void pollRunningHubTasks() {
List<AiTask> allTasks = aiTaskMapper.findProcessingTasksByProvider("runninghub");
// 分批处理每批50个
int batchSize = 50;
for (int i = 0; i < allTasks.size(); i += batchSize) {
List<AiTask> batch = allTasks.subList(i, Math.min(i + batchSize, allTasks.size()));
// 并发查询这批任务
batch.parallelStream().forEach(task -> {
try {
pollSingleTask(task);
} catch (Exception e) {
log.error("轮询任务失败: {}", task.getTaskNo(), e);
}
});
}
}
```
**预期性能:**
- 轮询时间~15秒/分批并发
- CPU使用率<50%
- 内存占用<4GB
- 网络带宽~10MB/分钟
---
### 方案C极致优化企业级
**目标:** 支持 **2000+并发任务**
**架构升级:**
1. **Redis消息队列** 替代数据库轮询
2. **独立轮询服务** 部署多个实例
3. **负载均衡** 分散WebSocket连接
4. **限流熔断** 保护RunningHub API
```mermaid
graph LR
A[用户请求] --> B[API网关]
B --> C[业务服务集群]
C --> D[Redis队列]
D --> E1[轮询服务1]
D --> E2[轮询服务2]
D --> E3[轮询服务3]
E1 --> F[RunningHub API]
E2 --> F
E3 --> F
F --> G[MySQL主从]
C --> H[WebSocket集群]
```
---
## 📈 五、RunningHub API限流策略
### 5.1 客户端限流(防止自身被封)
```java
@Component
public class RunningHubRateLimiter {
private final RateLimiter submitLimiter = RateLimiter.create(10.0); // 每秒10个提交
private final RateLimiter queryLimiter = RateLimiter.create(50.0); // 每秒50个查询
public void beforeSubmit() {
submitLimiter.acquire(); // 阻塞直到获得许可
}
public void beforeQuery() {
queryLimiter.acquire();
}
}
```
### 5.2 熔断降级RunningHub故障时
```java
@Service
public class RunningHubProviderImpl implements AIProvider {
@HystrixCommand(
fallbackMethod = "submitTaskFallback",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "10000"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50")
}
)
public ProviderTaskResponse submitTask(ProviderTaskRequest request) {
// 正常提交逻辑
}
public ProviderTaskResponse submitTaskFallback(ProviderTaskRequest request) {
log.error("RunningHub服务降级任务提交失败");
return ProviderTaskResponse.builder()
.status(TaskSubmitStatus.FAILED)
.errorMessage("RunningHub服务暂时不可用请稍后重试")
.build();
}
}
```
---
## 🧪 六、压力测试方案
### 6.1 测试工具
**JMeter测试脚本**
```xml
<HTTPSamplerProxy>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8081</stringProp>
<stringProp name="HTTPSampler.path">/user/ai/tasks/submit</stringProp>
<stringProp name="HTTPSampler.method">POST</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<ThreadGroup>
<intProp name="ThreadGroup.num_threads">100</intProp>
<intProp name="ThreadGroup.ramp_time">10</intProp>
<intProp name="LoopController.loops">1</intProp>
</ThreadGroup>
</HTTPSamplerProxy>
```
### 6.2 测试场景
#### 场景1渐进式压力测试
```bash
# 阶段110并发持续1分钟
# 阶段250并发持续5分钟
# 阶段3100并发持续10分钟
# 阶段4200并发持续10分钟
```
**观察指标:**
- API响应时间P50P95P99
- 轮询延迟
- 数据库连接池使用率
- CPU/内存使用率
- RunningHub API错误率
#### 场景2峰值冲击测试
```bash
# 突然提交500个任务观察系统恢复能力
ab -n 500 -c 100 -T 'application/json' \
-H "Authorization: Bearer TEST_TOKEN" \
-p task_payload.json \
http://localhost:8081/user/ai/tasks/submit
```
---
## 📊 七、监控与告警
### 7.1 关键指标
```sql
-- 实时并发任务数
SELECT COUNT(*) as running_tasks
FROM ai_task
WHERE provider_type = 'runninghub'
AND status = 'processing';
-- 平均处理时间
SELECT AVG(TIMESTAMPDIFF(SECOND, start_time, complete_time)) as avg_seconds
FROM ai_task
WHERE provider_type = 'runninghub'
AND status = 'completed'
AND complete_time > DATE_SUB(NOW(), INTERVAL 1 HOUR);
-- 失败率
SELECT
COUNT(CASE WHEN status = 'failed' THEN 1 END) * 100.0 / COUNT(*) as failure_rate
FROM ai_task
WHERE provider_type = 'runninghub'
AND create_time > DATE_SUB(NOW(), INTERVAL 1 HOUR);
```
### 7.2 告警规则
```yaml
alerts:
- name: "RunningHub并发过高"
condition: running_tasks > 200
action: 发送邮件/短信通知
- name: "RunningHub失败率过高"
condition: failure_rate > 10%
action: 触发熔断,停止新任务提交
- name: "轮询延迟过高"
condition: polling_delay > 30s
action: 重启轮询调度器
```
---
## 💡 八、最佳实践建议
### 8.1 初期部署100并发以内
1. 使用**方案A配置**
2. 轮询间隔设置为 **10秒**已调整
3. 监控RunningHub API响应时间
4. 每日检查失败任务并分析原因
### 8.2 业务增长期100-500并发
1. 升级到**方案B配置**
2. 实施分批轮询优化
3. 增加数据库连接池和Tomcat线程数
4. 引入限流和熔断机制
### 8.3 大规模部署500+并发)
1. 采用**方案C架构**
2. 独立部署轮询服务集群
3. 使用Redis消息队列
4. 实施全链路监控和自动告警
---
## 📝 九、RunningHub API费用估算
### 9.1 任务成本分析
根据 `V5__add_provider_support.sql` 中的积分配置
| 模型类型 | 积分消耗 | 实际成本假设1元=100积分 |
|---------|---------|---------------------------|
| 文生视频10秒普通 | 160 | 1.6元 |
| 文生视频10秒高清 | 420 | 4.2元 |
| 图生视频10秒普通 | 180 | 1.8元 |
| 图生视频10秒高清 | 480 | 4.8元 |
### 9.2 并发成本估算
**场景100个并发任务/小时**
假设任务分布
- 60% 文生视频普通60 × 1.6元 = 96元
- 20% 文生视频高清20 × 4.2元 = 84元
- 15% 图生视频普通15 × 1.8元 = 27元
- 5% 图生视频高清5 × 4.8元 = 24元
**总计231元/小时** **5544元/天**
**建议:**
- 对于高频用户设置每日任务数量限制
- 引入会员等级高级会员享受折扣
- 批量购买积分时提供优惠
---
## ✅ 十、总结与建议
### 当前配置(已优化)
```yaml
polling-interval: 10000 # ✅ 已改为10秒
max-polling-times: 60 # ✅ 已调整为60次
```
### 并发能力评估
| 并发任务数 | 系统负载 | 推荐配置 | 风险等级 |
|-----------|---------|---------|---------|
| 0-100 | | 方案A | 安全 |
| 100-200 | | 方案A | 注意 |
| 200-500 | | 方案B | 风险 |
| 500+ | 极高 | 方案C | 需重构 |
### 下一步行动
1. **短期1周内**
- [ ] 部署当前配置10秒轮询
- [ ] 监控前100个任务的表现
- [ ] 收集RunningHub API响应时间数据
2. **中期1个月内**
- [ ] 进行渐进式压力测试
- [ ] 找到RunningHub API的并发阈值
- [ ] 根据实际情况调整轮询间隔
3. **长期3个月内**
- [ ] 如果并发超过200实施方案B
- [ ] 引入Redis队列和独立轮询服务
- [ ] 建立完善的监控和告警体系
---
**RunningHub并发分析完成** 🎯
当前配置已优化为10秒轮询建议从小规模开始逐步增加并发实时监控系统表现