Как Официантка обрабатывает параллельные задачи? - PullRequest
8 голосов
/ 21 января 2020

Я пытаюсь создать python веб-сервер, используя Django и Waitress, но мне хотелось бы знать, как Waitress обрабатывает параллельные запросы и когда может блокировать .


Хотя в документации официантки упоминается о наличии нескольких рабочих потоков, в ней не содержится много информации о том, как они реализованы, и как python GIL влияет на них (выделено мое ):

Когда канал определяет, что клиент отправил хотя бы один полный действительный HTTP-запрос, он планирует «задачу» с «диспетчером потоков». Диспетчер потоков поддерживает фиксированный пул рабочих потоков, доступных для выполнения клиентской работы (по умолчанию 4 потока). Если рабочий поток доступен при планировании задачи, рабочий поток запускает задачу. Задача имеет доступ к каналу и может выполнить обратную запись в выходной буфер канала. Когда все рабочие потоки используются , запланированные задачи будут ждать в очереди , чтобы рабочий поток стал доступным.

Кажется, что нет Также много информации о Stackoverflow. Из вопроса «Является ли gicread asyn c от Gunicorn аналогом Waitress?» :

Официантка имеет основной асин c поток, который буферизует запросы и ставит в очередь каждый запрос к одному из его рабочих потоков syn c, когда ввод-вывод запроса завершен.


Эти операторы не обращаются к GIL (по крайней мере, насколько я понимаю), и это было бы здорово, если бы кто-то мог подробнее рассказать о том, как рабочие потоки работают для Waitress. Спасибо!

1 Ответ

1 голос
/ 13 марта 2020

Вот как обычно работают управляемые событиями асинхронные серверы:

  • Запустите процесс и прослушайте входящие запросы. Использование API уведомлений о событиях операционной системы позволяет очень просто обслуживать тысячи клиентов из одного потока / процесса.
  • Поскольку существует только один процесс, управляющий всеми соединениями, выполнять медленные операции не требуется ( или блокирование) задач в этом процессе. Потому что тогда он будет блокировать программу для каждого клиента.
  • Для выполнения задач блокировки сервер делегирует эти задачи «работникам». Рабочие могут быть потоками (запущенными в одном и том же процессе) или отдельными процессами (или подпроцессами). Теперь основной процесс может продолжать обслуживать клиентов, пока работники выполняют задачи блокировки.

Как Официантка обрабатывает параллельные задачи?

Примерно так же, как я только что описал выше. И для рабочих это создает потоки, а не процессы.

как python GIL влияет на них

Официантка использует потоки для рабочих. Итак, да, GIL влияет на них в том смысле, что они на самом деле не параллельны, хотя, похоже, так и есть. «Асинхронный» - это правильный термин.

Потоки в Python работают внутри одного процесса на одном ядре ЦП и не работают параллельно. Поток получает GIL в течение очень небольшого промежутка времени и выполняет свой код, а затем GIL получает другой поток.

Но поскольку GIL высвобождается при сетевом вводе-выводе, родительский процесс всегда получает GIL всякий раз, когда происходит сетевое событие (например, входящий запрос), и таким образом вы можете быть уверены, что GIL не будет влияют на связанные с сетью операции (например, получение запросов или отправку ответа).

С другой стороны, Python процессы фактически параллельны: они могут работать параллельно на нескольких ядрах. Но официантка не использует процессы.

Должны ли вы волноваться?

Если вы просто выполняете небольшие блокирующие задачи, такие как чтение / запись базы данных и обслуживаете только несколько сотен пользователей в секунду, то используйте потоки на самом деле не так уж и плохо.

Для обслуживания большого количества пользователей или выполнения длительных задач блокировки вы можете использовать внешние очереди задач, такие как Celery . Это будет намного лучше, чем сам создавать и управлять процессами.

...