我正在編寫一個基於Flask,gevent和Redis的Web應用程序,它使用了Server Sent Events。Flask + gevent - SSE超時nginx + uwsgi
我已經經歷了StackOverflow上的幾個問題,並在谷歌上進行了廣泛的搜索,但沒有找到適合我的任何合適的答案,所以在這裏我要求社區幫助。
問題出在生產堆棧nginx + uwsgi:瀏覽器定期收到更新(並按預期刷新)約30秒。之後,連接超時並且瀏覽器不再接收任何更新,直到手動重新加載頁面。
由於整個事情在本地主機上完美工作,使用標準的燒瓶開發服務器(連接在30分鐘空閒後活着),我很確定問題出在uwsgi/nginx配置上。我已經嘗試了所有我能想到的nginx/uwsgi設置,但沒有任何設置,它會在幾秒鐘後超時。
有沒有人有線索?
這裏有一些代碼和配置。
nginx的相關生產設置:
location/{
include uwsgi_params;
uwsgi_pass unix:/tmp/myapp.sock;
uwsgi_param UWSGI_PYHOME /srv/www/myapp/venv;
uwsgi_param UWSGI_CHDIR /srv/www/myapp;
uwsgi_param UWSGI_MODULE run;
uwsgi_param UWSGI_CALLABLE app;
uwsgi_buffering off;
proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;
proxy_cache off;
}
uwsgi生產設置
[uwsgi]
base = /srv/www/myapp
app = run
home = %(base)/venv
pythonpath = %(base)
socket = /tmp/%n.sock
gevent = 100
module = %(app)
callable = app
logto = /srv/www/myapp-logs/uwsgi_%n.log
這是模板執行訂閱頻道(暫時的JavaScript,模板只是刷新整個頁面當服務器推送一些數據時)
<script type="text/javascript">
var eventOutputContainer = document.getElementById("event");
var evtSrc = new EventSource("/movers/monitor");
evtSrc.onmessage = function(e) {
console.log(e.data);
location.reload();
//eventOutputContainer.innerHTML = e.data;
};
</script>
This是我用返回流數據
from myapp import redislist
from flask import Response, Blueprint, stream_with_context
movers = Blueprint('movers', __name__, url_prefix='/movers')
r = redislist['r']
@movers.route("/monitor")
def stream_movers():
def gen():
pubsub = r.pubsub()
pubsub.subscribe('movers-real-time')
for event in pubsub.listen():
if event['type'] == 'message':
yield 'retry: 10000\n\ndata: %s\n\n' % event['data']
return Response(stream_with_context(gen()), direct_passthrough=True, mimetype="text/event-stream")
,最後應用程序是這樣執行的代碼(DEBUG爲真在localhost)
from myapp import app
from gevent.wsgi import WSGIServer
if __name__ == '__main__':
DEBUG = True if app.config['DEBUG'] else False
if DEBUG:
app.run(debug=DEBUG, threaded=True)
app.debug = True
server = WSGIServer(("", 5000), app)
server.serve_forever()
else:
server = WSGIServer("", app)
server.serve_forever()