fix(websocket): 修复代理配置加载竞态条件导致的连接超时问题#183
Merged
chenyme merged 1 commit intochenyme:mainfrom Feb 19, 2026
Merged
Conversation
- Fix an issue where WebSocket connections (e.g., for image generation) failed with "semaphore timeout" because proxy settings were not applied. - Root cause: WebSocketClient was fetching proxy config during module-level instantiation, which occurred before config.load() finished. - Modified WebSocketClient to dynamically resolve proxy settings at connection time. - Added debug logging for proxy resolution and connector types.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📝 问题背景
在受限网络环境下,用户反馈图片生成(Imagine WebSocket)接口频繁报错:
WebSocket connect failed: Cannot connect to host grok.com:443 [The semaphore timeout period has expired]该错误表明应用在尝试直接连接
grok.com时超时,未能正确使用用户配置的代理服务器。🔍 原因分析
经过排查,发现项目中存在配置加载竞态条件:
ImagineWebSocketReverse服务在应用启动的模块导入阶段(import)即被实例化。lifespan尚未运行,异步配置加载await config.load()还没有执行,因此get_config("proxy.base_proxy_url")返回的是默认的空字符串。WebSocketClient在__init__中锁定了这个空值,导致后续所有连接都绕过了代理进行直连。✨ 修复方案
WebSocketClient类,将代理地址的读取逻辑从__init__移动到connect异步方法中。确保在实际发起网络请求时,能够读取到已经加载完成的data/config.toml配置。app/services/reverse/utils/websocket.py中增加了调试日志,记录每次连接时解析出的代理 URL 和 Connector 类型,方便排查网络问题。aiohttp.ws_connect在传递**extra_kwargs时的类型提示错误,提升了代码的健壮性。🛠️ 影响范围
WebSocketClient的底层连接(包括实时语音 LiveKit 接口)。✅ 验证建议
重启应用后观察日志,确认出现以下调试信息:
DEBUG | WebSocket connect: proxy_url=http://127.0.0.1:1080, resolved_proxy=http://127.0.0.1:1080, connector=TCPConnector