SSE超时nginx + uwsgi

我正在编写一个基于Flask,gevent和Redis的webapp,它使用了Server Sent Events。

我在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>

这是我用来返回流数据的代码

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: 10000nndata: %snn' % event['data']

    return Response(stream_with_context(gen()), direct_passthrough=True, mimetype="text/event-stream")

最后这个应用程序是这样执行的(DEBUG在本地主机上是True)

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()

在nginx日志文件和firefox js控制台上花了很长时间之后,发现问题中显示的配置完全正确。

问题是页面重新加载,这个操作杀死并重新初始化连接,因此重试命令没有任何作用。

删除该指令后,即使长时间不活动,SSE更新仍然像魅力一样工作。

现在的问题是为什么这在更简单的开发环境堆栈上工作:-)

编辑

事实上,几天之后,连接仍然超时。 我已经做了一些时间测量,发现超时间隔在30秒和几分钟不活动之间是可变的。

我的结论是,上面的堆栈是好的,而它是亚马逊EC2连接,在一些变量不活动时间后过期,因为我仍然使用微型实例。

最终的解决方案是以下JS代码片段:

    evtSrc.onerror = function(e) {
        location.reload();
    }

页面重新加载时连接被删除(无论原因)。 当服务器发送事件频繁时,预计不会发生重新加载。

链接地址: http://www.djcxy.com/p/18291.html

上一篇: SSE times out with nginx+uwsgi

下一篇: Prestashop Custom / Calculated Product Price