IIS反向代理部署Flask-SocketIO时WebSocket升级失败问题求助
解决方案步骤
1. 修改IIS反向代理规则,透传WebSocket握手头
现有web.config的入站规则漏了WebSocket必须的Upgrade和Connection头透传,直接替换ReverseProxyInboundRule1规则内容:
<rule name="ReverseProxyInboundRule1" enabled="true" stopProcessing="true"> <match url="(.*)" /> <action type="Rewrite" url="http://127.0.0.1:4441/{R:1}" /> <serverVariables> <set name="HTTP_X_FORWARDED_PORT" value="4440" /> <set name="HTTP_X_FORWARDED_HOST" value="subdomain.domain.co.uk" /> <set name="HTTP_X_FORWARDED_PROTO" value="https" /> <!-- 新增以下两行,透传WebSocket握手头 --> <set name="HTTP_CONNECTION" value="{HTTP_CONNECTION}" /> <set name="HTTP_UPGRADE" value="{HTTP_UPGRADE}" /> </serverVariables> <conditions> <!-- 新增条件匹配WebSocket升级请求 --> <add input="{HTTP_UPGRADE}" pattern="websocket" ignoreCase="true" negate="false" /> </conditions> </rule>
配置完成后需要在IIS对应站点的「URL重写」->「查看服务器变量」中,添加HTTP_CONNECTION和HTTP_UPGRADE到允许列表,否则配置不会生效。
2. 禁用IIS对Socket.io路径的压缩和缓冲
在system.webServer节点下新增以下配置,避免WebSocket流量被压缩、缓冲导致连接中断:
<system.webServer> <!-- 原有配置保持不变,新增以下内容 --> <urlCompression doStaticCompression="true" doDynamicCompression="false" /> <httpCompression> <dynamicTypes> <add mimeType="text/*" enabled="false" /> <add mimeType="application/json" enabled="false" /> <add mimeType="application/javascript" enabled="false" /> </dynamicTypes> </httpCompression> <caching enabled="false" enableKernelCache="false" /> </system.webServer>
3. 调整Flask-SocketIO服务端配置
将ProxyFix中间件的初始化位置调整到socketio.init_app之前,确保SocketIO的请求也能正确获取反向代理的转发信息,同时指定允许的传输方式:
# __init__.py修改后内容 from werkzeug.middleware.proxy_fix import ProxyFix from flask_socketio import SocketIO # 先套ProxyFix,再初始化socketio if not app.debug: app.wsgi_app = ProxyFix(app.wsgi_app, x_port=1, x_proto=1, x_host=1) socketio.init_app( app, logger=True, engineio_logger=True, cors_allowed_origins="https://subdomain.domain.co.uk:4440", # 新增以下配置,优先走websocket transports=['websocket', 'polling'], allow_upgrades=True ) return app
4. 调整客户端初始化配置
明确指定客户端优先使用WebSocket传输,避免无意义的长轮询重试:
$(document).ready(function() { // 新增transports参数,指定优先websocket var socket = io('/<NAMESPACE>', { transports: ['websocket', 'polling'], upgrade: true }); socket.on('connect', function() { socket.emit('joined', {room: <ROOM_NAME>}); }); });
5. 验证IIS全局配置
- 打开IIS管理器,进入「应用程序请求路由缓存」->「服务器代理设置」,将「超时」值调整为至少120秒,避免长连接被提前断开
- 确认站点对应应用池的「托管管道模式」为「集成」,「启用32位应用程序」设置为False
- 重启IIS站点和Flask-SocketIO服务后再测试
按照以上步骤配置完成后,即可正常看到Received request to upgrade to websocket的成功日志,WebSocket连接可以正常建立,不会再出现批量长轮询请求和BrokenPipe报错。
内容的提问来源于stack exchange,提问作者lc-51
相关产品推荐
相关产品推荐

