Gunicorn async и threaded workers для django

Async

Для ввода/вывода (IO) нам нужно использовать асинхронный код, а django не является асинхронным по умолчанию, но мы можем достичь этого, запустив gunicorn с gevent worker и monkey patching:

gunicorn --worker-class=gevent --worker-connections=1000 --workers=3 main:app

Gunicorn changelog от 2014 года https://docs.gunicorn.org/en/stable/2014-news.html?highlight=monkey#gevent-worker:

исправление: исправление обезьяны теперь выполняется в рабочем

  1. Do i still need to monkey patch my app or it's done by default from a worker ?
  2. How did gevent achieve async functionality for my django code ?

Потоки

Если у нас есть привязка к процессору, нам нужно использовать gthread worker с потоками:

gunicorn --workers=5 --threads=2 --worker-class=gthread main:app
  1. If we use this configuration for i/o bound, does it work? When one thread is waiting because of i/o, will the other thread be able to work?
  2. I see the point in (3) (if I'm right) because of the wait time in i/o, but if this is a CPU bound, how in our case will the second thread help us or will it only help if the core is not fully loaded by one thread and there is room for another to run?
  3. Are (3) and (4) useless because of GIL ?
    For example, 4 people sending request to server with 1 worker and 4 threads. GIL make sure that only 1 thread works. First man start processing with thread 1 and other 3 are waiting ? What are the threads for, then?
  1. Нужно ли мне еще патчить свое приложение или это делается по умолчанию из рабочего приложения?
    Не нужно ничего исправлять в вашем коде. Нет необходимости изменять код вообще.

  2. Как gevent добился асинхронной функциональности для моего кода django ?
    патчи все.gunicorn

  3. Если мы используем эту конфигурацию для i/o bound, это работает? Когда один поток ожидает из-за i/o, сможет ли другой поток работать?

    . Эта конфигурация работает для i/o bound. Потоки могут переключаться между собой в любое время (переключение контролируется в конечном итоге операционной системой), независимо от того, выполняет ли текущий поток ввод-вывод или вычисления, связанные с процессором. Несколько потоков могут работать одновременно на многопоточных процессорах. В отличие от них, гринлеты представляют собой скорее корутины, чем потоки. Если корутина блокируется вводом/выводом, она активно позволяет другой корутине взять контроль над процессором и выполнять действия, не связанные с вводом/выводом
    .

  4. Я вижу смысл в (3) (если я прав) из-за времени ожидания в i/o, но если это ограничение процессора, как в нашем случае второй поток поможет нам или он поможет только если ядро не полностью загружено одним потоком и есть место для другого? Для чисто процессорной задачи на однопоточном процессоре дополнительные потоки имеют мало смысла.


  5. Являются ли (3) и (4) бесполезными из-за GIL?
  6. GIL запрещает одновременный запуск ваших Python-кодов, но gunicorn в основном использует свои библиотеки, написанные не на Python. Вы не можете запускать свои коды Django (на Python) с несколькими потоками, но задачи ввода-вывода (обрабатываемые gunicorn, а не Python) могут идти параллельно. Если вам нужна загрузка процессора, используйте несколько процессов (

    ) вместо нескольких gthreads, или рассмотрите не-Python интерпретаторы, такие как
    , которые не ограничены GIL, но могут быть несовместимы с вашими кодами.workers=2 * CPU_THREADS + 1. pypy

Вернуться на верх