通过Gunicorn + Flask加载事件流

Ada*_*ele 7 python event-stream gevent flask gunicorn

我正在尝试使用Flask应用程序生成大型PDF。pdf生成包括生成十个长pdf,然后将它们合并在一起。该应用程序使用带有标志的Gunicorn运行:--worker-class gevent --workers 2。

我的服务器端代码如下所示:

@app.route ('/pdf/create', methods=['POST', 'GET'])
def create_pdf():
    def generate():
        for section in pdfs:
            yield "data: Generating %s pdf\n\n" % section
            # Generate pdf with pisa (takes up to 2 minutes)

        yield "data:  Merging PDFs\n\n"
        # Merge pdfs (takes up to 2 minutes)
        yield "data: /user/pdf_filename.pdf\n\n"

    return Response(stream_with_context(generate()), mimetype='text/event-stream')
Run Code Online (Sandbox Code Playgroud)

客户端代码如下所示:

var source = new EventSource(create_pdf_url);
source.onopen = function (event) {
  console.log("Creating PDF")
}
source.onmessage = function (event) {
    console.log(event.data);
}
source.onerror = function (event) {
    console.log("ERROR");
}
Run Code Online (Sandbox Code Playgroud)

没有 GUnicorn的情况下运行时,会从控制台日志中获得稳定,实时的更新。他们看起来像:

Creating PDF
Generating section one
Generating section two
Generating section three
...
Generating section ten
Merging PDFS
/user/pdf_filename.pdf
Run Code Online (Sandbox Code Playgroud)

当我在Gunicorn上运行此代码,不会得到定期更新。工作者运行直到Gunicorn的超时将其杀死为止,然后我转储了所有应该发生的消息转储,然后出现最终错误

Creating PDF
Generating section one
Generating section two
ERROR
Run Code Online (Sandbox Code Playgroud)

Gunicorn日志看起来像:

[2015-03-19 21:57:27 +0000] [3163] [CRITICAL] WORKER TIMEOUT (pid:3174)
Run Code Online (Sandbox Code Playgroud)

如何防止Gunicorn杀死进程?我认为设置超大超时不是一个好主意。也许在gunicorn的worker类中可以使用某些东西来确保正确处理该过程?

Ada*_*ele 1

我最终使用 Celery 解决了这个问题。

我用这个例子来指导我设置 Celery。

然后我使用Grinberg 的 Celery 教程将实时更新传输到用户的浏览器。