Тайм-аут из-за конвейера ресурсов фляги, когда отладка отключена

У меня есть приложение на основе Flask, которое использует flask-assets для объединения, компиляции и минимизации CSS и Javascript. Тайм-аут происходит, когда я запускаю приложение с Gunicorn, используя

gunicorn --bind=0.0.0.0:8000 --workers=3 --log-level=INFO manage:app

Сообщение о тайм-ауте гласит:

[2018-04-01 11:15:13 +0000] [10] [INFO] Starting gunicorn 19.6.0
[2018-04-01 11:15:13 +0000] [10] [INFO] Listening at: http://0.0.0.0:8000 (10)
[2018-04-01 11:15:13 +0000] [10] [INFO] Using worker: sync
[2018-04-01 11:15:13 +0000] [16] [INFO] Booting worker with pid: 16
[2018-04-01 11:15:13 +0000] [17] [INFO] Booting worker with pid: 17
[2018-04-01 11:15:13 +0000] [18] [INFO] Booting worker with pid: 18
[2018-04-01 11:15:46 +0000] [10] [CRITICAL] WORKER TIMEOUT (pid:17)
[2018-04-01 11:15:47 +0000] [17] [INFO] Worker exiting (pid: 17)
[2018-04-01 11:15:47 +0000] [19] [INFO] Booting worker with pid: 19

Я определил активы в assets.py файл с содержанием

from flask_assets import Bundle

app_css = Bundle('app.scss', filters='libsass', output='styles/app.css')

app_js = Bundle('app.js', filters='jsmin', output='scripts/app.js')

vendor_css = Bundle(
    'vendor/semantic.css',
    filters='cssmin',
    output='styles/vendor.css')

vendor_js = Bundle(
    'vendor/jquery.min.js',
    'vendor/semantic.min.js',
    'vendor/tablesort.min.js',
    'vendor/zxcvbn.js',
    filters='jsmin',
    output='scripts/vendor.js')

Соответствующая часть в основном приложении __init__.py является

from flask_assets import Environment

from .assets import app_css, app_js, vendor_css, vendor_js

def create_app(config_name):
    ...
    # Set up asset pipeline
    assets_env = Environment(app)
    dirs = ['assets/styles', 'assets/scripts']
    for path in dirs:
        assets_env.append_path(os.path.join(basedir, path))
    assets_env.url_expire = True

    assets_env.register('app_css', app_css)
    assets_env.register('app_js', app_js)
    assets_env.register('vendor_css', vendor_css)
    assets_env.register('vendor_js', vendor_js)

Вопрос в том, как можно избежать тайм-аута? Можно ли предварительно скомпилировать ресурсы до того, как Gunicorn начнет ждать?

1 ответ

Решение

Решение требует двух изменений для работы, включая предварительную нагрузку для gunicorn и запуск конвейера активов на заводе. Чтобы включить предварительную загрузку, добавьте --preload к команде оружейного:

gunicorn --bind=0.0.0.0:8000 --workers=3 --preload --log-level=INFO manage:app

Если не указано иное, конвейер активов будет выполняться лениво, т. Е. Когда его активы сначала запрашиваются запросом. Это означает, что если build() явно не вызывается, первый запрос будет заблокирован и, возможно, время ожидания. Поэтому для каждого Bundle пакет вызова объекта в create_app функция:

app_css.build()
app_js.build()
vendor_css.build()
vendor_js.build()

Если в gunicorn включена только предварительная загрузка или пакет, ранее не скомпилированный явно, команда сборки вызывается с первым запросом, а затем по тайм-ауту.

Бонус: чтобы ускорить сборку Travis CI, добавьте app/static/.webassets-cache в кеш в .travis.yml с:

cache:
  pip: true
  directories:
    - core/app/static/.webassets-cache
Другие вопросы по тегам