【发布时间】: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