Flask-SocketIO - WebSocket 在连接建立之前关闭。 [Heroku]
Posted
技术标签:
【中文标题】Flask-SocketIO - WebSocket 在连接建立之前关闭。 [Heroku]【英文标题】:Flask-SocketIO - WebSocket is closed before the connection is established. [Heroku] 【发布时间】:2021-12-11 15:31:23 【问题描述】:在我的本地服务器上运行 Flask 时一切都很好,但是在迁移到 Heroku 之后,我开始收到“WebSocket 在建立连接之前已关闭”。 在我的本地服务器中,websocket 连接了一次,但在 heroku 上,它一直连接到 websocket。
Heroku 日志
2021-10-26T08:23:02.637338+00:00 app[web.1]: [2021-10-26 08:23:02 +0000] [4] [CRITICAL] WORKER TIMEOUT (pid:43)
2021-10-26T08:23:02.637839+00:00 app[web.1]: [2021-10-26 08:23:02 +0000] [43] [INFO] Worker exiting (pid: 43)
2021-10-26T08:23:02.729197+00:00 app[web.1]: [2021-10-26 08:23:02 +0000] [45] [INFO] Booting worker with pid: 45
2021-10-26T08:23:03.105363+00:00 heroku[router]: at=info method=GET path="/socket.io/?EIO=4&transport=websocket" host=chatroom-private.herokuapp.com request_id=c6a836a6-5fbd-4e6b-8d21-bd97d72513e4 fwd="103.86.182.226" dyno=web.1 connect=0ms service=15569ms status=101 bytes=129 protocol=https
2021-10-26T08:23:03.105683+00:00 app[web.1]: Traceback (most recent call last):
2021-10-26T08:23:03.105716+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/gevent/pywsgi.py", line 999, in handle_one_response
2021-10-26T08:23:03.105717+00:00 app[web.1]: self.run_application()
2021-10-26T08:23:03.105719+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/geventwebsocket/handler.py", line 75, in run_application
2021-10-26T08:23:03.105719+00:00 app[web.1]: self.run_websocket()
2021-10-26T08:23:03.105728+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/geventwebsocket/handler.py", line 52, in run_websocket
2021-10-26T08:23:03.105729+00:00 app[web.1]: list(self.application(self.environ, lambda s, h, e=None: []))
2021-10-26T08:23:03.105731+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/flask/app.py", line 2091, in __call__
2021-10-26T08:23:03.105731+00:00 app[web.1]: return self.wsgi_app(environ, start_response)
2021-10-26T08:23:03.105742+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/flask_socketio/__init__.py", line 43, in __call__
2021-10-26T08:23:03.105742+00:00 app[web.1]: return super(_SocketIOMiddleware, self).__call__(environ,
2021-10-26T08:23:03.105749+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/engineio/middleware.py", line 63, in __call__
2021-10-26T08:23:03.105750+00:00 app[web.1]: return self.engineio_app.handle_request(environ, start_response)
2021-10-26T08:23:03.105757+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/socketio/server.py", line 589, in handle_request
2021-10-26T08:23:03.105758+00:00 app[web.1]: return self.eio.handle_request(environ, start_response)
2021-10-26T08:23:03.105760+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/engineio/server.py", line 379, in handle_request
2021-10-26T08:23:03.105760+00:00 app[web.1]: r = self._handle_connect(environ, start_response,
2021-10-26T08:23:03.105769+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/engineio/server.py", line 554, in _handle_connect
2021-10-26T08:23:03.105769+00:00 app[web.1]: ret = s.handle_get_request(environ, start_response)
2021-10-26T08:23:03.105776+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/engineio/socket.py", line 103, in handle_get_request
2021-10-26T08:23:03.105776+00:00 app[web.1]: return getattr(self, '_upgrade_' + transport)(environ,
2021-10-26T08:23:03.105783+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/engineio/socket.py", line 158, in _upgrade_websocket
2021-10-26T08:23:03.105783+00:00 app[web.1]: return ws(environ, start_response)
2021-10-26T08:23:03.105790+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/engineio/async_drivers/eventlet.py", line 16, in __call__
2021-10-26T08:23:03.105791+00:00 app[web.1]: raise RuntimeError('You need to use the eventlet server. '
2021-10-26T08:23:03.105807+00:00 app[web.1]: RuntimeError: You need to use the eventlet server. See the Deployment section of the documentation for more information.
2021-10-26T08:23:03.105880+00:00 app[web.1]: 2021-10-26T08:23:03Z 'REMOTE_ADDR': '10.1.95.245', 'REMOTE_PORT': '29183', 'HTTP_HOST': 'chatroom-private.herokuapp.com', (hidden keys: 39) failed with RuntimeError
2021-10-26T08:23:03.105881+00:00 app[web.1]:
2021-10-26T08:23:03.515546+00:00 heroku[router]: at=info method=GET path="/socket.io/?EIO=4&transport=websocket" host=chatroom-private.herokuapp.com request_id=27a8989f-fda3-46c1-9e5f-c9e3a5354c49 fwd="103.86.182.226" dyno=web.1 connect=0ms service=1ms status=101 bytes=129 protocol=https
2021-10-26T08:23:03.512553+00:00 app[web.1]: Traceback (most recent call last):
2021-10-26T08:23:03.512578+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/gevent/pywsgi.py", line 999, in handle_one_response
2021-10-26T08:23:03.512579+00:00 app[web.1]: self.run_application()
2021-10-26T08:23:03.512581+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/geventwebsocket/handler.py", line 75, in run_application
2021-10-26T08:23:03.512581+00:00 app[web.1]: self.run_websocket()
2021-10-26T08:23:03.512590+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/geventwebsocket/handler.py", line 52, in run_websocket
2021-10-26T08:23:03.512590+00:00 app[web.1]: list(self.application(self.environ, lambda s, h, e=None: []))
2021-10-26T08:23:03.512592+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/flask/app.py", line 2091, in __call__
2021-10-26T08:23:03.512593+00:00 app[web.1]: return self.wsgi_app(environ, start_response)
2021-10-26T08:23:03.512613+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/flask_socketio/__init__.py", line 43, in __call__
2021-10-26T08:23:03.512613+00:00 app[web.1]: return super(_SocketIOMiddleware, self).__call__(environ,
2021-10-26T08:23:03.512620+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/engineio/middleware.py", line 63, in __call__
2021-10-26T08:23:03.512620+00:00 app[web.1]: return self.engineio_app.handle_request(environ, start_response)
2021-10-26T08:23:03.512628+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/socketio/server.py", line 589, in handle_request
2021-10-26T08:23:03.512628+00:00 app[web.1]: return self.eio.handle_request(environ, start_response)
2021-10-26T08:23:03.512630+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/engineio/server.py", line 379, in handle_request
2021-10-26T08:23:03.512630+00:00 app[web.1]: r = self._handle_connect(environ, start_response,
2021-10-26T08:23:03.512639+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/engineio/server.py", line 554, in _handle_connect
2021-10-26T08:23:03.512639+00:00 app[web.1]: ret = s.handle_get_request(environ, start_response)
2021-10-26T08:23:03.512646+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/engineio/socket.py", line 103, in handle_get_request
2021-10-26T08:23:03.512646+00:00 app[web.1]: return getattr(self, '_upgrade_' + transport)(environ,
2021-10-26T08:23:03.512653+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/engineio/socket.py", line 158, in _upgrade_websocket
2021-10-26T08:23:03.512653+00:00 app[web.1]: return ws(environ, start_response)
2021-10-26T08:23:03.512660+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/engineio/async_drivers/eventlet.py", line 16, in __call__
2021-10-26T08:23:03.512661+00:00 app[web.1]: raise RuntimeError('You need to use the eventlet server. '
2021-10-26T08:23:03.512675+00:00 app[web.1]: RuntimeError: You need to use the eventlet server. See the Deployment section of the documentation for more information.
2021-10-26T08:23:03.512745+00:00 app[web.1]: 2021-10-26T08:23:03Z 'REMOTE_ADDR': '10.1.23.225', 'REMOTE_PORT': '13370', 'HTTP_HOST': 'chatroom-private.herokuapp.com', (hidden keys: 39) failed with RuntimeError
2021-10-26T08:23:03.512746+00:00 app[web.1]:
2021-10-26T08:23:03.513320+00:00 app[web.1]: Traceback (most recent call last):
2021-10-26T08:23:03.513345+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/eventlet/hubs/hub.py", line 476, in fire_timers
2021-10-26T08:23:03.513345+00:00 app[web.1]: timer()
2021-10-26T08:23:03.513352+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/eventlet/hubs/timer.py", line 59, in __call__
2021-10-26T08:23:03.513353+00:00 app[web.1]: cb(*args, **kw)
2021-10-26T08:23:03.513361+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/eventlet/semaphore.py", line 152, in _do_acquire
2021-10-26T08:23:03.513362+00:00 app[web.1]: waiter.switch()
2021-10-26T08:23:03.513363+00:00 app[web.1]: File "src/gevent/greenlet.py", line 910, in gevent._gevent_cgreenlet.Greenlet.run
2021-10-26T08:23:03.513373+00:00 app[web.1]: File "src/gevent/greenlet.py", line 875, in gevent._gevent_cgreenlet.Greenlet._Greenlet__report_result
2021-10-26T08:23:03.513381+00:00 app[web.1]: File "src/gevent/_gevent_cgreenlet.pxd", line 45, in gevent._gevent_cgreenlet.get_my_hub
2021-10-26T08:23:03.513393+00:00 app[web.1]: TypeError: Cannot convert greenlet.greenlet to gevent._gevent_c_greenlet_primitives.SwitchOutGreenletWithLoop
Python 服务器
app = Flask(__name__,instance_relative_config=False)
CORS(app)
app.config.from_object('config.Config')
app.config['CORS_HEADERS'] = 'Content-Type'
socketio = SocketIO(app,cors_allowed_origins='*')
@app.route("/",methods=['GET', 'POST'])
def index():
return render_template('index.html',)
@socketio.on('message')
def handleMessage(msg):
print('Message: ' + msg)
send(msg, broadcast=True)
if __name__ == '__main__':
port = int(os.environ.get('PORT', 5000))
socketio.run(app,port=port)
客户
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.3.2/socket.io.js" crossorigin="anonymous">
var connectionOptions =
"force new connection" : true,
"reconnectionAttempts": "Infinity", //avoid having user reconnect manually in order to prevent dead clients after a server restart
"timeout" : 10000, //before connect_error and connect_timeout are emitted.
"transports" : ["websocket"]
;
$(document).ready(function()
const socket = io(connectionOptions);
过程文件
web: gunicorn -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 1 app:app
【问题讨论】:
请修剪您的代码,以便更容易找到您的问题。请按照以下指南创建minimal reproducible example。 【参考方案1】:你看到差异了吗?您正在使用 gevent-websocket 工作者运行 Gunicorn,但 Flask-SocketIO 认为它已配置为使用 eventlet:
RuntimeError: You need to use the eventlet server. See the Deployment section of the documentation for more information.
你想用哪一个?如果您想要 gevent,则将 async_mode='gevent' 添加到您的 SocketIO() 对象中,以覆盖默认值。或者作为替代方案,确保您的 virtualenv 中没有安装 eventlet,然后 Flask-SocketIO 将使用下一个选项,即 gevent。
【讨论】:
以上是关于Flask-SocketIO - WebSocket 在连接建立之前关闭。 [Heroku]的主要内容,如果未能解决你的问题,请参考以下文章