Websocket(Python 3.5 中的 ws4py)无法在 Docker 容器中工作
Websocket (ws4py in Python 3.5) not working in Docker container
我有一个简单的 Web 应用程序,它使用 CherryPy 作为 RESTful 后端,使用 ws4py 作为 websockets。
1) Javascript client sends a POST to Python backend
2) Python replies with a unique id
3) Javascript connects to the websocket and sends the unique id
4) Python associates the websocket client connection to the unique id
Python 网络套接字代码:
class WebSocketHandler(WebSocket):
def __init__(self, *args, **kw):
WebSocket.__init__(self, *args, **kw)
print('Connected to websocket server!')
SUBSCRIBERS.add(self)
def received_message(self, message):
print('Websocket identified itself?')
SUBSCRIBERS_WITH_ID[message.data] = self
Python CherryPy代码:
cherrypy.config.update({'server.socket_host': 0.0.0.0,
'server.socket_port': 8080})
cherrypy.tools.CORS = cherrypy.Tool('before_handler', CORS)
WebSocketPlugin(cherrypy.engine).subscribe()
cherrypy.tools.websocket = WebSocketTool()
cherrypy.tree.mount(
DummyAPI(), '/api/dummy', config={
'/': {
'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
'tools.CORS.on': True
}
}
)
cherrypy.tree.mount(
WebSocketAPI(), '/ws', config={
'/': {
'tools.websocket.on': True,
'tools.websocket.handler_cls': WebSocketHandler
}
}
)
cherrypy.engine.start()
cherrypy.engine.block()
Javascript代码:
POST 到 API:
var req = new XMLHttpRequest();
req.onload = function (e) {
console.log('Response code: ' + req.responseText);
result_id = req.responseText;
websocketConnect();
};
req.open('POST', api_url);
req.send();
Websocket 部分:
function websocketConnect() {
websocket = new WebSocket(websocket_url);
websocket.onopen = function (evt) {
console.log("Connected to WebSocket server.");
websocket.send(result_id)};
这在我的机器上运行良好并部署在 Amazon EC2 上。但是,当我尝试将它部署在 Docker 容器中时,websockets 不起作用。
这是我的Docker文件:
FROM python
MAINTAINER xxx
RUN pip3.5 install cherrypy ws4py
RUN mkdir /var/www
COPY python /var/www/python
EXPOSE 8080
CMD ["/usr/local/bin/python3.5", "/var/www/python/simplews.py"]
当我从Docker运行时输出:
sudo docker run -v /tmp/dockertmp/:/tmp/ -p 8080:8080 -i 563a51d13f59
[23/Oct/2015:10:09:00] ENGINE Bus STARTING
[23/Oct/2015:10:09:00] ENGINE Starting WebSocket processing
[23/Oct/2015:10:09:00] ENGINE Started monitor thread '_TimeoutMonitor'.
[23/Oct/2015:10:09:00] ENGINE Started monitor thread 'Autoreloader'.
[23/Oct/2015:10:09:01] ENGINE Serving on http://0.0.0.0:8080
[23/Oct/2015:10:09:01] ENGINE Bus STARTED
172.17.42.1 - - [23/Oct/2015:10:09:08] "POST ..."
Connected to websocket server!
它从未达到 Javascript 文件能够通过 websocket 发送数据的阶段。 Chrome 调试显示 WS 状态为 "Pending"。
但是,当我在Docker中退出CherryPy应用程序时,websocket消息通过:
enter code here
sudo docker run -v /tmp/dockertmp/:/tmp/ -p 8080:8080 -i 563a51d13f59
[23/Oct/2015:10:15:30] ENGINE Bus STARTING
[23/Oct/2015:10:15:30] ENGINE Starting WebSocket processing
[23/Oct/2015:10:15:30] ENGINE Started monitor thread '_TimeoutMonitor'.
[23/Oct/2015:10:15:30] ENGINE Started monitor thread 'Autoreloader'.
[23/Oct/2015:10:15:30] ENGINE Serving on http://0.0.0.0:8080
[23/Oct/2015:10:15:30] ENGINE Bus STARTED
172.17.42.1 - - [23/Oct/2015:10:15:33] "POST ..."
Connected to websocket server!
^C[23/Oct/2015:10:15:35] ENGINE Keyboard Interrupt: shutting down bus
[23/Oct/2015:10:15:35] ENGINE Bus STOPPING
[23/Oct/2015:10:15:40] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('0.0.0.0', 8080)) shut down
[23/Oct/2015:10:15:40] ENGINE Stopped thread '_TimeoutMonitor'.
[23/Oct/2015:10:15:40] ENGINE Terminating WebSocket processing
[23/Oct/2015:10:15:40] ENGINE Stopped thread 'Autoreloader'.
[23/Oct/2015:10:15:40] ENGINE Bus STOPPED
[23/Oct/2015:10:15:40] ENGINE Bus EXITING
[23/Oct/2015:10:15:40] ENGINE Bus EXITED
[23/Oct/2015:10:15:40] ENGINE Waiting for child threads to terminate...
Websocket identified itself?
当我运行没有Docker时输出:
python3.5 python/simplews.py
[23/Oct/2015:06:09:45] ENGINE Bus STARTING
[23/Oct/2015:06:09:45] ENGINE Starting WebSocket processing
[23/Oct/2015:06:09:45] ENGINE Started monitor thread '_TimeoutMonitor'.
[23/Oct/2015:06:09:45] ENGINE Started monitor thread 'Autoreloader'.
[23/Oct/2015:06:09:45] ENGINE Serving on http://0.0.0.0:8080
[23/Oct/2015:06:09:45] ENGINE Bus STARTED
127.0.0.1 - - [23/Oct/2015:06:09:48] "POST ..."
Connected to websocket server!
Websocket identified itself?
在非 Docker 情况下,websocket 会立即识别自己。我想不通。 websocket 接收器线程是否以某种方式卡在 Docker 中?
Docker 日志中的可疑部分是当应用程序退出时,websocket 收到的消息终于到达:
[23/Oct/2015:10:15:40] ENGINE Waiting for child threads to terminate...
Websocket identified itself?
用 threading.Thread 替换 Python 多处理模块解决了这个问题。我在 POST 方法处理程序中使用多处理。
这是对实际项目进行修复的提交:
https://github.com/sevagh/youtube-audio-dl/commit/9e23ae174f8791206b934608a1d4d702b411d18e
我有一个简单的 Web 应用程序,它使用 CherryPy 作为 RESTful 后端,使用 ws4py 作为 websockets。
1) Javascript client sends a POST to Python backend
2) Python replies with a unique id
3) Javascript connects to the websocket and sends the unique id
4) Python associates the websocket client connection to the unique id
Python 网络套接字代码:
class WebSocketHandler(WebSocket):
def __init__(self, *args, **kw):
WebSocket.__init__(self, *args, **kw)
print('Connected to websocket server!')
SUBSCRIBERS.add(self)
def received_message(self, message):
print('Websocket identified itself?')
SUBSCRIBERS_WITH_ID[message.data] = self
Python CherryPy代码:
cherrypy.config.update({'server.socket_host': 0.0.0.0,
'server.socket_port': 8080})
cherrypy.tools.CORS = cherrypy.Tool('before_handler', CORS)
WebSocketPlugin(cherrypy.engine).subscribe()
cherrypy.tools.websocket = WebSocketTool()
cherrypy.tree.mount(
DummyAPI(), '/api/dummy', config={
'/': {
'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
'tools.CORS.on': True
}
}
)
cherrypy.tree.mount(
WebSocketAPI(), '/ws', config={
'/': {
'tools.websocket.on': True,
'tools.websocket.handler_cls': WebSocketHandler
}
}
)
cherrypy.engine.start()
cherrypy.engine.block()
Javascript代码:
POST 到 API:
var req = new XMLHttpRequest();
req.onload = function (e) {
console.log('Response code: ' + req.responseText);
result_id = req.responseText;
websocketConnect();
};
req.open('POST', api_url);
req.send();
Websocket 部分:
function websocketConnect() {
websocket = new WebSocket(websocket_url);
websocket.onopen = function (evt) {
console.log("Connected to WebSocket server.");
websocket.send(result_id)};
这在我的机器上运行良好并部署在 Amazon EC2 上。但是,当我尝试将它部署在 Docker 容器中时,websockets 不起作用。
这是我的Docker文件:
FROM python
MAINTAINER xxx
RUN pip3.5 install cherrypy ws4py
RUN mkdir /var/www
COPY python /var/www/python
EXPOSE 8080
CMD ["/usr/local/bin/python3.5", "/var/www/python/simplews.py"]
当我从Docker运行时输出:
sudo docker run -v /tmp/dockertmp/:/tmp/ -p 8080:8080 -i 563a51d13f59
[23/Oct/2015:10:09:00] ENGINE Bus STARTING
[23/Oct/2015:10:09:00] ENGINE Starting WebSocket processing
[23/Oct/2015:10:09:00] ENGINE Started monitor thread '_TimeoutMonitor'.
[23/Oct/2015:10:09:00] ENGINE Started monitor thread 'Autoreloader'.
[23/Oct/2015:10:09:01] ENGINE Serving on http://0.0.0.0:8080
[23/Oct/2015:10:09:01] ENGINE Bus STARTED
172.17.42.1 - - [23/Oct/2015:10:09:08] "POST ..."
Connected to websocket server!
它从未达到 Javascript 文件能够通过 websocket 发送数据的阶段。 Chrome 调试显示 WS 状态为 "Pending"。
但是,当我在Docker中退出CherryPy应用程序时,websocket消息通过:
enter code here
sudo docker run -v /tmp/dockertmp/:/tmp/ -p 8080:8080 -i 563a51d13f59
[23/Oct/2015:10:15:30] ENGINE Bus STARTING
[23/Oct/2015:10:15:30] ENGINE Starting WebSocket processing
[23/Oct/2015:10:15:30] ENGINE Started monitor thread '_TimeoutMonitor'.
[23/Oct/2015:10:15:30] ENGINE Started monitor thread 'Autoreloader'.
[23/Oct/2015:10:15:30] ENGINE Serving on http://0.0.0.0:8080
[23/Oct/2015:10:15:30] ENGINE Bus STARTED
172.17.42.1 - - [23/Oct/2015:10:15:33] "POST ..."
Connected to websocket server!
^C[23/Oct/2015:10:15:35] ENGINE Keyboard Interrupt: shutting down bus
[23/Oct/2015:10:15:35] ENGINE Bus STOPPING
[23/Oct/2015:10:15:40] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('0.0.0.0', 8080)) shut down
[23/Oct/2015:10:15:40] ENGINE Stopped thread '_TimeoutMonitor'.
[23/Oct/2015:10:15:40] ENGINE Terminating WebSocket processing
[23/Oct/2015:10:15:40] ENGINE Stopped thread 'Autoreloader'.
[23/Oct/2015:10:15:40] ENGINE Bus STOPPED
[23/Oct/2015:10:15:40] ENGINE Bus EXITING
[23/Oct/2015:10:15:40] ENGINE Bus EXITED
[23/Oct/2015:10:15:40] ENGINE Waiting for child threads to terminate...
Websocket identified itself?
当我运行没有Docker时输出:
python3.5 python/simplews.py
[23/Oct/2015:06:09:45] ENGINE Bus STARTING
[23/Oct/2015:06:09:45] ENGINE Starting WebSocket processing
[23/Oct/2015:06:09:45] ENGINE Started monitor thread '_TimeoutMonitor'.
[23/Oct/2015:06:09:45] ENGINE Started monitor thread 'Autoreloader'.
[23/Oct/2015:06:09:45] ENGINE Serving on http://0.0.0.0:8080
[23/Oct/2015:06:09:45] ENGINE Bus STARTED
127.0.0.1 - - [23/Oct/2015:06:09:48] "POST ..."
Connected to websocket server!
Websocket identified itself?
在非 Docker 情况下,websocket 会立即识别自己。我想不通。 websocket 接收器线程是否以某种方式卡在 Docker 中?
Docker 日志中的可疑部分是当应用程序退出时,websocket 收到的消息终于到达:
[23/Oct/2015:10:15:40] ENGINE Waiting for child threads to terminate...
Websocket identified itself?
用 threading.Thread 替换 Python 多处理模块解决了这个问题。我在 POST 方法处理程序中使用多处理。
这是对实际项目进行修复的提交:
https://github.com/sevagh/youtube-audio-dl/commit/9e23ae174f8791206b934608a1d4d702b411d18e