Skip to content

Commit 3ef8559

Browse files
committed
重大实施:加入多workers以支援并发
1 parent 23d65c7 commit 3ef8559

File tree

15 files changed

+1209
-61
lines changed

15 files changed

+1209
-61
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
## 🚀 特性
2424

2525
- **OpenAI 兼容 API**: 完全兼容 OpenAI 格式的 `/v1/chat/completions` 端点
26+
- **多 Worker 并发**: 支持多账号并发处理,提升吞吐量和稳定性
2627
- **TTS 语音生成**: 支持 Gemini 2.5 TTS 模型的单/多说话人音频生成
2728
- **图片生成**: 支持 Imagen 3 和 Gemini 2.5 Flash (Nano Banana) 图片生成
2829
- **视频生成**: 支持 Veo 2 视频生成,包含图片转视频功能
@@ -323,6 +324,8 @@ AIStudio2API/
323324
│ ├── tts/ # TTS 语音生成模块
324325
│ ├── media/ # 媒体生成模块 (Imagen/Veo/Nano)
325326
│ ├── proxy/ # 流式代理
327+
│ ├── worker/ # 多Worker管理模块
328+
│ ├── gateway.py # 多Worker负载均衡网关
326329
│ └── static/ # 静态资源
327330
├── data/ # 运行时数据目录
328331
│ ├── auth_profiles/ # 认证文件
@@ -379,6 +382,7 @@ cp .env.example .env
379382
- [环境变量配置](docs/environment-configuration.md)
380383
- [认证设置](docs/authentication-setup.md)
381384
- [API 使用指南](docs/api-usage.md)
385+
- [多Worker并发模式](docs/multi-worker-guide.md)
382386
- [故障排除](docs/troubleshooting.md)
383387

384388
## ⚠️ 重要提示
@@ -408,4 +412,4 @@ cp .env.example .env
408412
- **Go 语言重构**: 将核心代理服务迁移至 Go 以提升并发性能与降低资源占用
409413
- **CI/CD 流水线**: 建立 GitHub Actions 自动化测试与构建发布流程
410414
- **单元测试**: 增加核心模块(特别是浏览器自动化部分)的测试覆盖率
411-
- **负载均衡**: 支持多 Google 账号轮询池,以提高并发限额与稳定性 (这项或许不可能实现)
415+
- **多Worker负载均衡**: 支持多 Google 账号轮询池,提高并发限额与稳定性 (这项或许不可能实现) (fix:2025/12/09 这项已实现)

README_en.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
## 🚀 Features
2424

2525
- **OpenAI Compatible API**: Fully compatible with OpenAI format `/v1/chat/completions` endpoint
26+
- **Multi-Worker Concurrency**: Supports multi-account concurrent processing for improved throughput and stability
2627
- **TTS Speech Generation**: Supports Gemini 2.5 TTS models for single/multi-speaker audio generation
2728
- **Image Generation**: Supports Imagen 3 and Gemini 2.5 Flash (Nano Banana) image generation
2829
- **Video Generation**: Supports Veo 2 video generation, including image-to-video
@@ -317,6 +318,8 @@ AIStudio2API/
317318
│ ├── tts/ # TTS Speech Generation modules
318319
│ ├── media/ # Media Generation modules (Imagen/Veo/Nano)
319320
│ ├── proxy/ # Streaming proxy
321+
│ ├── worker/ # Multi-Worker management module
322+
│ ├── gateway.py # Multi-Worker load balancing gateway
320323
│ └── static/ # Static resources
321324
├── data/ # Runtime data directory
322325
│ ├── auth_profiles/ # Authentication files
@@ -373,6 +376,7 @@ Supports accessing AI Studio through proxy:
373376
- [Environment Configuration](docs/environment-configuration.md)
374377
- [Authentication Setup](docs/authentication-setup.md)
375378
- [API Usage Guide](docs/api-usage.md)
379+
- [Multi-Worker Concurrency Mode](docs/multi-worker-guide.md)
376380
- [Troubleshooting](docs/troubleshooting.md)
377381

378382
## ⚠️ Important Notes
@@ -402,5 +406,5 @@ Issues and Pull Requests are welcome!
402406
- **Go Refactoring**: Migrate core proxy service to Go for improved concurrency and reduced resource usage
403407
- **CI/CD Pipeline**: Establish GitHub Actions automated testing and build release process
404408
- **Unit Testing**: Increase test coverage for core modules (especially browser automation)
405-
- **Load Balancing**: Support multi-Google account rotation pool for higher concurrency limits
409+
- **Multi-Worker Load Balancing**: Support multi-Google account rotation pool for higher concurrency limits
406410

data/workers.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"workers": [
3+
{
4+
"id": "w1",
5+
"profile": "auth_auto_1764657832.json",
6+
"port": 3001,
7+
"camoufox_port": 9222
8+
},
9+
{
10+
"id": "w2",
11+
"profile": "auth_auto_1764657915.json",
12+
"port": 3002,
13+
"camoufox_port": 9223
14+
},
15+
{
16+
"id": "w3",
17+
"profile": "auth_auto_1764658826.json",
18+
"port": 3003,
19+
"camoufox_port": 9224
20+
},
21+
{
22+
"id": "w4",
23+
"profile": "auth_auto_1765180693.json",
24+
"port": 3004,
25+
"camoufox_port": 9225
26+
}
27+
],
28+
"settings": {
29+
"recovery_hours": 6.0
30+
}
31+
}

docs/development-guide.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,16 @@ AIStudio2API/
7373
│ │ ├── server.py # 代理服务器
7474
│ │ ├── handler.py # 请求处理器
7575
│ │ └── connection.py # 连接/证书管理
76+
│ ├── worker/ # 多Worker管理模块
77+
│ │ ├── models.py # Worker数据模型
78+
│ │ └── pool.py # Worker池管理
7679
│ ├── logger/ # 日志工具
7780
│ │ └── config.py # 日志配置
7881
│ ├── static/ # 静态资源
7982
│ ├── app_launcher.py # GUI 启动器
8083
│ ├── launch_camoufox.py # 命令行启动器
8184
│ ├── manager.py # WebUI 管理器
85+
│ ├── gateway.py # 多Worker负载均衡网关
8286
│ └── server.py # 主服务器
8387
├── data/ # 运行时数据目录
8488
│ ├── auth_profiles/ # 认证文件存储

docs/multi-worker-guide.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# 多 Worker 并发模式
2+
3+
多 Worker 模式允许您使用多个 Google 账号同时处理 API 请求,显著提升系统吞吐量和稳定性。
4+
5+
## 概述
6+
7+
在多 Worker 模式下:
8+
- 每个 Worker 对应一个独立的 Google 账号(认证文件)
9+
- Gateway 网关自动将请求分发到可用的 Worker
10+
- 所有 Worker 共享同一个外部 API 端口(默认 2048)
11+
- 支持流式响应和完整的思考过程透传
12+
13+
## 快速开始
14+
15+
### 1. 添加多个认证文件
16+
17+
首先需要为每个 Google 账号创建认证文件:
18+
19+
1. 启动有头模式,完成第一个账号的登录认证
20+
2. 认证文件自动保存到 `data/auth_profiles/saved/` 目录
21+
3. 重复上述步骤为其他账号创建认证文件
22+
23+
### 2. 配置 Workers
24+
25+
1. 打开 Web 管理界面 `http://127.0.0.1:9000`
26+
2. 进入「认证文件」标签页(现在称为「Worker 管理」)
27+
3. 从已保存的认证文件列表中,点击「添加为 Worker」
28+
4. 确认 Worker 列表中显示所有要使用的账号
29+
5. **点击「保存配置」按钮**保存 Worker 池配置
30+
31+
### 3. 启用 Worker 模式
32+
33+
1. 在 Worker 管理页面,开启「Worker 模式」开关
34+
2. 点击「保存配置」
35+
3. 返回主页,点击「启动服务」
36+
37+
### 4. 使用 API
38+
39+
与单 Worker 模式完全相同,所有请求发送到同一端口:
40+
41+
```bash
42+
curl -X POST http://localhost:2048/v1/chat/completions \
43+
-H "Content-Type: application/json" \
44+
-d '{
45+
"model": "gemini-2.5-pro",
46+
"messages": [{"role": "user", "content": "Hello!"}],
47+
"stream": true
48+
}'
49+
```
50+
51+
## 架构说明
52+
53+
```
54+
客户端请求
55+
56+
Gateway (端口 2048)
57+
↓ 轮询分发
58+
+----+----+----+----+
59+
| W1 | W2 | W3 | W4 | (各自独立端口 3001, 3002, ...)
60+
+----+----+----+----+
61+
62+
Google AI Studio
63+
```
64+
65+
## 配置文件
66+
67+
Worker 配置保存在 `data/workers.json`
68+
69+
```json
70+
{
71+
"workers": [
72+
{"id": "w1", "profile": "account1.json", "port": 3001, "camoufox_port": 9223},
73+
{"id": "w2", "profile": "account2.json", "port": 3002, "camoufox_port": 9224}
74+
],
75+
"settings": {"recovery_hours": 6}
76+
}
77+
```
78+
79+
## 日志过滤
80+
81+
多 Worker 模式下日志量较大,可使用主页的日志过滤功能:
82+
83+
- **来源筛选**: 选择 Gateway / Worker-w1 / Worker-w2 等单独查看
84+
85+
## 注意事项
86+
87+
1. **端口分配**: 每个 Worker 自动分配独立端口,避免冲突
88+
2. **流式代理端口**: Worker-w1 使用 3120,Worker-w2 使用 3121,以此类推
89+
3. **账号安全**: 确保每个账号的认证文件独立,不要共用
90+
4. **资源占用**: 每个 Worker 运行独立的浏览器实例,注意内存占用
91+
92+
## 常见问题
93+
94+
### Q: 为什么某些请求没有响应?
95+
检查目标 Worker 的日志,确认浏览器实例正常运行。
96+
97+
### Q: 如何扩展更多 Worker?
98+
添加更多认证文件,然后在 Worker 管理中添加即可。重启服务生效。
99+
100+
### Q: 认证文件过期怎么办?
101+
需要重新进入有头模式登录对应账号,更新认证文件。

src/browser/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from .initialization import _initialize_page_logic, _close_page_logic, signal_camoufox_shutdown
2-
from .operations import _handle_model_list_response, detect_and_extract_page_error, save_error_snapshot, get_response_via_edit_button, get_response_via_copy_button, _wait_for_response_completion, _get_final_response_content, get_raw_text_content
2+
from .operations import _handle_model_list_response, detect_and_extract_page_error, detect_rate_limit, save_error_snapshot, get_response_via_edit_button, get_response_via_copy_button, _wait_for_response_completion, _get_final_response_content, get_raw_text_content
33
from .model_management import switch_ai_studio_model, load_excluded_models, _handle_initial_model_state_and_storage, _set_model_from_page_display, _verify_ui_state_settings, _force_ui_state_settings, _force_ui_state_with_retry, _verify_and_apply_ui_state
44
from .script_manager import ScriptManager, script_manager
55
__all__ = ['_initialize_page_logic', '_close_page_logic', 'signal_camoufox_shutdown', '_handle_model_list_response', 'detect_and_extract_page_error', 'save_error_snapshot', 'get_response_via_edit_button', 'get_response_via_copy_button', '_wait_for_response_completion', '_get_final_response_content', 'get_raw_text_content', 'switch_ai_studio_model', 'load_excluded_models', '_handle_initial_model_state_and_storage', '_set_model_from_page_display', '_verify_ui_state_settings', '_force_ui_state_settings', '_force_ui_state_with_retry', '_verify_and_apply_ui_state', 'ScriptManager', 'script_manager']

src/browser/operations.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,20 @@ async def detect_and_extract_page_error(page: AsyncPage, req_id: str) -> Optiona
362362
logger.warning(f'[{req_id}] 检查页面错误时出错: {e}')
363363
return None
364364

365+
async def detect_rate_limit(page: AsyncPage, req_id: str) -> tuple:
366+
try:
367+
locator = page.locator(RATE_LIMIT_CALLOUT_SELECTOR).last
368+
if await locator.count() > 0:
369+
text = await locator.text_content(timeout=500)
370+
if text:
371+
for kw in RATE_LIMIT_KEYWORDS:
372+
if kw in text.lower():
373+
logger.warning(f'[{req_id}] ⚠️ Rate Limit detected: {text.strip()}')
374+
return True, text.strip()
375+
except:
376+
pass
377+
return False, ""
378+
365379
async def save_error_snapshot(error_name: str='error'):
366380
import server
367381
name_parts = error_name.split('_')

src/config/selectors.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,6 @@
4343
THINKING_LEVEL_OPTION_HIGH_SELECTOR = 'mat-option:has-text("High")'
4444
THINKING_LEVEL_OPTION_LOW_SELECTOR = 'mat-option:has-text("Low")'
4545
DEFAULT_THINKING_LEVEL = "high"
46+
47+
RATE_LIMIT_CALLOUT_SELECTOR = 'ms-callout.error-callout .message, ms-callout.warning-callout .message'
48+
RATE_LIMIT_KEYWORDS = ["exceeded quota", "out of free generations"]

0 commit comments

Comments
 (0)