使用Eventlet在Flask中管理SocketIO

11

我正在尝试搭建一个处理HTTP和socketio请求的小型服务器 - 我没有太多设置服务器的经验,但现在apache2可以很好地服务HTTP请求。然而,socketio事务会出现400错误代码(坏请求),在服务器日志中我看到一些奇怪的错误。有时我会看到engineio错误并且服务器会用“坏请求”和代码400响应,但总是告诉我需要启动eventlet服务器:

[Mon Jan 11 19:02:54.068282 2016] [:error] [pid 4908:tid 140274923673344] [client 100.96.180.39:53473]     return ws(environ, start_response)
[Mon Jan 11 19:02:54.068305 2016] [:error] [pid 4908:tid 140274923673344] [client 100.96.180.39:53473]   File "/var/www/projectENV/lib/python2.7/site-packages/engineio/async_eventlet.py", line 10, in __call__
[Mon Jan 11 19:02:54.068342 2016] [:error] [pid 4908:tid 140274923673344] [client 100.96.180.39:53473]     raise RuntimeError('You need to use the eventlet server.')
[Mon Jan 11 19:02:54.068380 2016] [:error] [pid 4908:tid 140274923673344] [client 100.96.180.39:53473] RuntimeError: You need to use the eventlet server. See the Deployment section of the documentation for more information.
[Mon Jan 11 19:02:54.253124 2016] [:error] [pid 4909:tid 140274940458752] WARNING:engineio:Invalid session cde3f9aadbee4794bf9d7bb98d0b396e

我的服务器代码很基本:

 from flask import Flask
 import flaskext.couchdb
 from flask.ext.socketio import SocketIO

 # for socketio
 import eventlet
 eventlet.monkey_patch()

 # creation of server & db objects
 app = Flask(__name__)

 # socketio initialization
 socketio =  SocketIO(app, async_mode='eventlet')

 # import views once site properties are set
 from app import views

 if __name__== "__main__":
     socketio.run(app, debug=True)

我的客户端代码使用 Python 编写,直接从文档中使用 socketio-client 库:

from socketIO_client import SocketIO, LoggingNamespace
with SocketIO(SERVER_URL, 80, LoggingNamespace) as socketIO:
    socketIO.emit('aaa')
    socketIO.wait(seconds=1)

socketio.run(app)不应该为我启动eventlet服务器吗?为什么服务器有时会返回错误请求?

1个回答

17
为了让WSGI应用程序在线上可用,您需要通过Web服务器公开它。当您的应用程序使用Flask-SocketIO时,普通的WSGI Web服务器是不够的,因为WSGI不支持WebSocket,WSGI协议需要非官方扩展来支持此协议。
Flask-SocketIO支持多种支持WebSocket的Web服务器。看起来您已经在虚拟环境中安装了eventlet,这就是为什么您收到错误消息,要求您使用eventlet Web服务器。
您似乎没有意识到的是,您正在使用Apache的Web服务器(我猜测是mod_wsgi?)。这个Web服务器是一个普通的分叉Web服务器,它不是一个与eventlet兼容的Web服务器。
“socketio.run(app)”不应该为我启动eventlet服务器吗?
是的,如果您通过“socketio.run(app)”运行应用程序,您将获得完全启用的eventlet Web服务器。但是您没有这样做,您正在apache上运行它。Eventlet有一个Web服务器,Apache也有一个Web服务器,它们是两个独立的Web服务器,都能运行WSGI应用程序。但是Apache的Web服务器不支持WebSocket。

Flask-SocketIO文档描述了几个有效的部署方案。


谢谢澄清!当我说我没有经验时,我绝对不是在开玩笑。如果我坚持使用长轮询,你知道为什么会出现关于坏请求的错误吗?它没有提供比那个错误更多的信息。 - zeck
1
为了使长轮询工作,服务器必须能够在同一进程中处理每个客户端的两个并发请求。因此,唯一能够使用长轮询的Web服务器是那些使用线程的服务器。分叉多进程Web服务器无法执行长轮询。 - Miguel Grinberg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接