feat: GPT 账户轮换与搜索韧性改进(代理池/重试/状态自动切换) - #31
Conversation
AI PR Review RefusedThis PR targets |
Adds a proxy pool system that allows importing proxies in bulk (IP:port:username:password format) and automatically distributing them round-robin across all accounts, so each account uses an independent outbound IP. - New service: proxy_pool_service with import/delete/assign/clear - Storage layer: load_proxy_pool/save_proxy_pool on all backends - Network layer: account_proxy parameter takes priority over global proxy - All providers (GPT/Grok/Gemini) now use per-account proxy when set - API endpoints: GET/POST/DELETE /api/proxy-pool, /assign, /clear - Frontend: proxy pool management card in Settings page
- Randomize _index on startup to avoid always hitting the same account after restart (was always 0 → first account gets rate-limited) - Add per-attempt 90s timeout to search handler with automatic account rotation (up to 3 retries with different accounts) - Fixes search hanging indefinitely when an account is silently rate-limited by ChatGPT (no error response, just hangs)
The search handler was wrapping _do_search in a ThreadPoolExecutor to add per-attempt timeouts. However, since LoggedCall.run() already executes handle() inside Starlette's run_in_threadpool, the nested executor created a thread-within-thread situation that deadlocked curl_cffi's libcurl. Fix: call backend.search() directly (no nested thread), relying on the internal SEARCH_TIMEOUT_SECS (reduced to 90s) and retrying with a different account on failure (up to 3 attempts).
- mark_search_failure: transition to 限流/异常/禁用 by error type (rate-limit/cloudflare → 限流 cooldown 15min, auth-invalid → 异常, 3x consecutive auth failures → 禁用); transient network errors ignored - mark search success: clear cooldown/异常 state and reset fail counter - list_limited_tokens now includes 异常 accounts so the watcher re-validates both - call mark_search_failure from the search retry path so degraded accounts exit rotation immediately instead of being retried on every request
c479c0f to
25ef6a4
Compare
AI PR Review FailedThe AI PR review could not be completed, so no review state was submitted. Reason: OpenAI API returned HTTP 503. |
1 similar comment
AI PR Review FailedThe AI PR review could not be completed, so no review state was submitted. Reason: OpenAI API returned HTTP 503. |
|
注意到 `AI PR Review` check 失败,查看日志显示: ``` 这是 review workflow 调用 OpenAI API 时上游返回的 HTTP 503(服务暂时不可用),属于上游瞬时故障,与本 PR 的代码改动无关。 另外最初一次失败是因为 PR base 误设为 `main`,而该 workflow 只审查 base 为 `dev` 的 PR。现已将 base 改为 `dev`,`PR Target Branch` check 已通过,4 个提交也已 rebase 到 `dev` 上(目标文件在 dev/main 间无差异,无冲突)。 当前 PR 状态:`mergeable`,无合并冲突,仅剩 AI review check 因上游 503 未通过。麻烦维护者有空时重跑一次 `AI PR Review` workflow 即可。谢谢! |
… integration) 把阶段一验证的订阅节点测活链路沉淀进项目,proxy_pool 可消费 VLESS 等加密协议节点访问 chatgpt.com(消费侧零改动,订阅 item 的 socks5://127.0.0.1:port 天然兼容 assign/curl_cffi)。 - mihomo_manager: mihomo 常驻进程管理 + listeners 多端口配置生成(内容指纹 node_id + 持久化 port_map,同节点跨 sync 端口稳定) - proxy_health_service: sync 闭环(拉订阅→筛地区→起 mihomo→curl_cffi 测 chatgpt.com→写 pool)+ 周期调度 + 异步 task_id 轮询 + 订阅源 CRUD + 单飞锁 - proxy_pool_service: item 扩展(source/protocol/health/latency 等)+ replace/delete_subscription_items + reassign_invalid_accounts(仅失效账号重分配,保 GPT 账号 IP 稳定) - storage 四实现(base/database/json/git)加 load/save_subscriptions - config 加 mihomo 配置项(port_base/sync_interval/test_url/region_keywords 等) - api/system.py 加 6 端点(订阅源 CRUD / sync / health) - api/app.py lifespan 启停 mihomo + health_service(启动失败降级,不拖垮主服务) - Dockerfile 下载 mihomo v1.19.27 二进制(amd64-compatible/arm64) - 前端 api.ts + proxy-pool-card.tsx 加订阅源管理 / 同步轮询 / 健康视图 UI - 新增 pyyaml 依赖(容器级验证抓到:开发时 --with 掩盖了运行时缺失) - scripts/sync_subscription.py(阶段一独立 CLI)+ test/test_proxy_subscription.py(8 项单测) 验证:单测 8/8 + 后端 E2E(67/134)+ API 冒烟 + 前端 build + 容器级真实 sync(61/123)
AI PR Review FailedThe AI PR review could not be completed, so no review state was submitted. Reason: OpenAI API returned HTTP 503. |
概述
本 PR 为 GPT 账户轮换机制带来一系列稳定性与韧性改进,核心目标:在持续负载下让退化账户(限流 / 鉴权失效)立即退出轮换,由后台 watcher 自动恢复或升级,避免被每个请求反复重试而级联拖垮整个账户池。
改动内容
每账户代理池 + 批量导入与自动分配 (
21190b5)为每个账户支持独立代理池,提供批量导入与自动分配,降低单 IP 被风控时波及多账户的风险。
随机账户索引 + 搜索重试与超时 (
373db65)轮换时随机选取起始索引避免热点;搜索请求加入带超时的重试,失败后自动切换到下一个账户。
移除搜索中嵌套的 ThreadPoolExecutor (
466fa68)修复嵌套线程池导致的死锁问题。
基于搜索结果自动切换账户状态 (
c479c0f)mark_search_failure:按错误类型自动将账户置为 限流 / 异常 / 禁用list_limited_tokens纳入异常账户,使 watcher 同时复验限流与异常mark_search_failure,让退化账户立即退出轮换动机
在持续负载下,单个退化账户若不主动退出轮换,会被每个请求反复重试,级联拖垮整个账户池。本 PR 让退化账户即时退出、由 watcher 自动恢复(限流 / 异常)或升级(禁用),维持账户池整体可用性,同时保留禁用账户以便后续批量重新加入。
测试
本地验证搜索成功 / 失败路径下的状态切换与自动恢复行为。
从 fork `zhu1090093659/gptweb2api` 提交,包含 4 个 commit。