【问题标题】:Flask SocketIO timeout when using web server instead of localhost使用 Web 服务器而不是 localhost 时 Flask SocketIO 超时
【发布时间】:2019-07-20 05:07:39
【问题描述】:

我正在使用 Flask 开发一个基本的网络消息传递应用程序,我正在使用带有 gunicorn 的 docker 作为代理服务器的 wsgi 和 nginx 进行部署。当我运行容器时,一切都在本地主机上运行,​​但是当我尝试通过套接字向远程服务器发送消息时出现错误,运行相同的容器星座。更具体地说,我被告知套接字超时。这很奇怪,因为所有非套接字交互都非常快,但实际上计算量并不高(在本地工作时消息几乎立即发送)。

我使用的套接字框架是 Flask-SocketIO,我正在使用 eventlet 处理消息。当用户发送消息时,我的接收和发送功能是使用以下代码完成的:

@socketio.on('post message')
def add_new_msg(data):
    data['isPending'] = False
    if len(data['message']) <= 0:
        return
    sql_query = 'INSERT INTO messages (chatroomid, messagecontent, timestamp, sendername) '
    sql_query += 'SELECT :chatroomid, :messagecontent, :timestamp, :sendername '
    sql_query += 'WHERE EXISTS (SELECT 1 FROM chatrooms WHERE chatroomid = :chatroomid)'
    row_count = db.execute(sql_query, {
                'chatroomid': data['roomId'],
                'messagecontent': data['message'],
                'timestamp': data['timestamp'],
                'sendername': data['username']
                }).rowcount
    db.commit()
    if row_count > 0:
        emit('server message callback', data, broadcast=True)

提前感谢您的任何建议。

编辑: 添加了错误日志。

app_1         | [2019-06-16 13:53:59 +0000] [8] [ERROR] Socket error processing request.
app_1         | Traceback (most recent call last):
app_1         |   File "/usr/local/lib/python3.6/site-packages/gunicorn/workers/base_async.py", line 66, in handle
app_1         |     six.reraise(*sys.exc_info())
app_1         |   File "/usr/local/lib/python3.6/site-packages/gunicorn/six.py", line 625, in reraise
app_1         |     raise value
app_1         |   File "/usr/local/lib/python3.6/site-packages/gunicorn/workers/base_async.py", line 56, in handle
app_1         |     self.handle_request(listener_name, req, client, addr)
app_1         |   File "/usr/local/lib/python3.6/site-packages/gunicorn/workers/base_async.py", line 129, in handle_request
app_1         |     six.reraise(*sys.exc_info())
app_1         |   File "/usr/local/lib/python3.6/site-packages/gunicorn/six.py", line 625, in reraise
app_1         |     raise value
app_1         |   File "/usr/local/lib/python3.6/site-packages/gunicorn/workers/base_async.py", line 107, in handle_request
app_1         |     respiter = self.wsgi(environ, resp.start_response)
app_1         |   File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 2309, in __call__
app_1         |     return self.wsgi_app(environ, start_response)
app_1         |   File "/usr/local/lib/python3.6/site-packages/flask_socketio/__init__.py", line 44, in __call__
app_1         |     start_response)
app_1         |   File "/usr/local/lib/python3.6/site-packages/engineio/middleware.py", line 59, in __call__
app_1         |     return self.engineio_app.handle_request(environ, start_response)
app_1         |   File "/usr/local/lib/python3.6/site-packages/socketio/server.py", line 428, in handle_request
app_1         |     return self.eio.handle_request(environ, start_response)
app_1         |   File "/usr/local/lib/python3.6/site-packages/engineio/server.py", line 340, in handle_request
app_1         |     environ, start_response)
app_1         |   File "/usr/local/lib/python3.6/site-packages/engineio/socket.py", line 106, in handle_get_request
app_1         |     start_response)
app_1         |   File "/usr/local/lib/python3.6/site-packages/engineio/socket.py", line 146, in _upgrade_websocket
app_1         |     return ws(environ, start_response)
app_1         |   File "/usr/local/lib/python3.6/site-packages/engineio/async_drivers/eventlet.py", line 20, in __call__
app_1         |     return super(WebSocketWSGI, self).__call__(environ, start_response)
app_1         |   File "/usr/local/lib/python3.6/site-packages/eventlet/websocket.py", line 130, in __call__
app_1         |     self.handler(ws)
app_1         |   File "/usr/local/lib/python3.6/site-packages/engineio/socket.py", line 160, in _websocket_handler
app_1         |     pkt = ws.wait()
app_1         |   File "/usr/local/lib/python3.6/site-packages/eventlet/websocket.py", line 788, in wait
app_1         |     for i in self.iterator:
app_1         |   File "/usr/local/lib/python3.6/site-packages/eventlet/websocket.py", line 643, in _iter_frames
app_1         |     message = self._recv_frame(message=fragmented_message)
app_1         |   File "/usr/local/lib/python3.6/site-packages/eventlet/websocket.py", line 669, in _recv_frame
app_1         |     header = recv(2)
app_1         |   File "/usr/local/lib/python3.6/site-packages/eventlet/websocket.py", line 578, in _get_bytes
app_1         |     d = self.socket.recv(numbytes - len(data))
app_1         |   File "/usr/local/lib/python3.6/site-packages/eventlet/greenio/base.py", line 366, in recv
app_1         |     return self._recv_loop(self.fd.recv, b'', bufsize, flags)
app_1         |   File "/usr/local/lib/python3.6/site-packages/eventlet/greenio/base.py", line 360, in _recv_loop
app_1         |     self._read_trampoline()
app_1         |   File "/usr/local/lib/python3.6/site-packages/eventlet/greenio/base.py", line 331, in _read_trampoline
app_1         |     timeout_exc=socket_timeout('timed out'))
app_1         |   File "/usr/local/lib/python3.6/site-packages/eventlet/greenio/base.py", line 210, in _trampoline
app_1         |     mark_as_closed=self._mark_as_closed)
app_1         |   File "/usr/local/lib/python3.6/site-packages/eventlet/hubs/__init__.py", line 159, in trampoline
app_1         |     return hub.switch()
app_1         |   File "/usr/local/lib/python3.6/site-packages/eventlet/hubs/hub.py", line 298, in switch
app_1         |     return self.greenlet.switch()
app_1         | socket.timeout: timed out

【问题讨论】:

  • 能否请您添加错误的完整副本?
  • 感谢您的回复 - 我已将其添加到问题中。
  • 你给标准库打补丁了吗?有关这方面的信息,请参阅 eventlet.net/doc/patching.html
  • 如何使用 Gunicorn 调用猴子补丁?或者我是否通过脚本运行补丁在单独的容器中执行此操作(它是否会永久影响 STL)?
  • Gunicorn 猴子补丁默认情况下,但这有时效果不佳,所以我猜这取决于您使用的 Gunicorn 版本。最好在您的代码中添加猴子补丁。这不是永久性的,请参阅我提供的链接,那里已经解释了所有内容。

标签: docker sockets nginx gunicorn flask-socketio


【解决方案1】:

嗯 - 我觉得这有点傻。在放弃并尝试向某人展示工作中的错误后,我发现该应用程序运行良好。就在那时,我意识到我家的 wifi 一定以某种方式阻止了服务器发回套接字响应。所以它真的很有效 - 感谢 Miguel 一直支持我!

【讨论】:

    猜你喜欢
    • 2016-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多