Загрузка потока событий через Gunicorn + Flask

Я пытаюсь создать большой PDF-файл с помощью приложения Flask. Генерация 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')

Код на стороне клиента выглядит так:

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");
}

Когда я запускаю без GUnicorn, я получаю постоянные обновления в режиме реального времени из журнала консоли. Они похожи:

Creating PDF
Generating section one
Generating section two
Generating section three
...
Generating section ten
Merging PDFS
/user/pdf_filename.pdf

Когда я запускаю этот код с Gunicorn, я не получаю регулярных обновлений. Рабочий работает до тех пор, пока тайм-аут Gunicorn не убьет его, затем я получаю дамп всех сообщений, которые должны были произойти, с последующим сообщением об ошибке.

Creating PDF
Generating section one
Generating section two
ERROR

Журнал Gunicorn выглядит так:

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

Как я могу удержать Gunicorn от прерывания процесса? Я не думаю, что установка сверхбольшого тайм-аута - хорошая идея. Возможно, в рабочих классах Gunicorn есть что-то, что я могу использовать, чтобы убедиться, что процесс выполняется правильно?


person Adam Steele    schedule 20.03.2015    source источник
comment
Второй source.onmessage должен быть source.onerror, но, вероятно, не связан с решением.   -  person Cory Danielson    schedule 20.03.2015
comment
Хороший улов. Отредактировано, чтобы исправить опечатку.   -  person Adam Steele    schedule 20.03.2015


Ответы (1)


В итоге я решил проблему с помощью сельдерея.

Я использовал этот пример, чтобы помочь мне настроить Celery.

Затем я использовал учебник Гринберга по сельдерею для потоковой передачи обновлений в реальном времени пользователю браузер.

person Adam Steele    schedule 30.03.2015