веб-серверы и серверы wsgi / asgi

Веб-сервер: когда клиент отправляет запрос на открытие веб-страницы, браузер должен откуда-то получить ответ, и это где-то веб-сервер. Теперь предположим, что есть приложение для игры:

клиент запускает игру, сервер ответил на него, теперь сервер может делать 2 вещи:

  1. Подождите, пока клиент сделает следующий ход.
  2. Проверьте, есть ли еще один клиент, который хочет играть, чтобы избежать блокировки.

NGINX - это веб-сервер, следующий за вторым пунктом.

Обратный прокси: принимает запрос от клиента, перенаправляет его на сервер, который может его выполнить, и возвращает ответ сервера клиенту.

NGINX также является обратным прокси. Мы можем делать кеширование, балансировку нагрузки и на NGINX.

Nginx использует асинхронный, управляемый событиями подход, при котором запросы обрабатываются в одном потоке. Есть один главный процесс, который контролирует несколько рабочих процессов. Каждый рабочий может обрабатывать большое количество одновременных подключений. Рабочие процессы являются однопоточными, а поскольку они асинхронны, это означает, что каждый запрос может выполняться рабочими одновременно, не блокируя другие запросы. Как в приведенном выше примере игры. Вы можете настроить NGINX в соответствии с вашими потребностями с помощью различных параметров. Два из них:

  • worker_processes: количество рабочих процессов NGINX (по умолчанию 1). В большинстве случаев хорошо работает один рабочий процесс / ядро ​​ЦП. Но вы можете настроить его соответствующим образом.
  • worker_connections: максимальное количество подключений, которые каждый рабочий процесс может обрабатывать одновременно. По умолчанию 512, но у большинства систем достаточно ресурсов для поддержки большего числа.

У нас вроде как были веб-серверы только в первые дни, а для запуска приложений на Python у нас был модуль mod_python. Но это не очень подходит для приложений Python. Поэтому люди решили определить некоторые стандарты, по которым веб-серверы могут взаимодействовать с приложениями Python. WSGI - это стандарт.

WSGI: интерфейс шлюза веб-сервера - это простое соглашение о вызовах веб-серверов для пересылки запросов веб-приложениям или фреймворкам, написанным на языке программирования Python.

WSGI состоит из двух частей: веб-сервера и приложения Python.

Таким образом, с помощью WSGI мы можем отделить код сервера от кода приложения, куда вы можете добавить свою бизнес-логику.

Существует множество фреймворков, в которых вы можете писать приложения Python, поддерживающие WSGI, такие как Django, CherryPy, Flask и т. Д., Но они недостаточно хороши для одновременной обработки тысяч запросов или они не знают, как лучше всего направить их с сервера. Поэтому нам как бы нужен другой сервер, на котором мы можем разместить наше приложение, работающее с веб-сервером.

Сервер приложений - это сервер, на котором размещаются приложения. А для приложений Python серверы приложений известны как серверы WSGI, поскольку они соответствуют стандартам WSGI.

Серверы WSGI используют свою конфигурацию для получения пути к приложению. Приложения WSGI - это один синхронный вызываемый объект, который принимает запрос и возвращает ответ. Его дизайн привязан к циклу запроса / ответа в стиле HTTP. Поэтому, если мы хотим добиться с ним долговременного соединения, он заблокирует сервер, а это не очень хорошо для приложений реального времени.

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

Итак, чтобы справиться со всеми этими людьми, внедрили стандарты ASGI. Его основная цель - предоставить способ написания кода HTTP / 2 и WebSocket наряду с обычным кодом обработки HTTP.

ASGI: интерфейс асинхронного серверного шлюза структурирован как единый асинхронный вызываемый. Приложения представляют собой асинхронные вызываемые объекты, а не простые вызываемые объекты, и они взаимодействуют с сервером, получая и отправляя асинхронные сообщения о событиях, а не получая один входной поток и возвращая один итеративный объект.

Требуется scope, который является dict, содержащий сведения о конкретном соединении, send, асинхронный вызываемый объект, который позволяет приложению отправлять сообщения о событиях клиенту, и receive, асинхронный вызываемый объект, который позволяет приложению получать сообщения о событиях от клиента.

Это не только разрешает несколько входящих и исходящих событий для каждого приложения, но также позволяет использовать фоновую сопрограмму, чтобы приложение могло делать другие вещи (например, прослушивать события внешнего триггера, например, очереди Redis).

Python никогда не запускает более 1 потока на процесс из-за GIL. Даже если у вас есть 100 потоков внутри вашего процесса, GIL позволит запускать только один поток одновременно. Это означает, что в любой момент 99 из этих потоков приостановлены, а 1 поток работает. Gunicorn - это способ обойти это ограничение.

Gunicorn: это сервер WSGI, основанный на модели воркеров до форка. Это означает, что существует центральный главный процесс, который управляет набором рабочих процессов. Мастер никогда ничего не знает об отдельных клиентах. Все запросы и ответы полностью обрабатываются рабочими процессами.

В Gunicorn мы можем определять различные параметры. Ниже приведены некоторые из них:

  1. worker: количество рабочих, которых вы хотите запустить. Как правило, рекомендуется создать (2 x $ num_cores) + 1 в качестве начального количества рабочих процессов.
  2. потоки: мы также можем определить много потоков / рабочих, по умолчанию это 1.
  3. Рабочий класс: рабочий класс определяет, как рабочие будут работать. Gunicorn предоставляет рабочие классы sync, gevent, evenlet, tornado, gthread. по умолчанию используется синхронизация.

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

Если вы попытаетесь использовать тип рабочего sync и установите для параметра threads значение больше 1, вместо него будет использоваться тип рабочего gthread.

Синхронизирующие рабочие процессы. Самый простой и стандартный рабочий тип - это синхронный рабочий класс, который одновременно обрабатывает один запрос.

Асинхронные рабочие процессы (gevent, evenlet) - доступные асинхронные рабочие процессы основаны на Greenlets (через Eventlet и Gevent).

Как мы знаем, python не запускает более одного потока, поэтому вам нужно увеличить количество рабочих. Но есть переломный момент, когда добавление дополнительных сотрудников отрицательно сказывается на производительности. Таким образом, мы можем выбрать рабочий класс async, который использует зеленые потоки (Greenlets). Вы получаете то преимущество, что НЕ нужно создавать потоки в ваших воркерах. Предположим, что вы получаете потоки без необходимости явно создавать их.

Greenlets, также известные как зеленые потоки, совместные потоки или сопрограммы, предоставляют потоки, но без использования потоков. Управление потоками осуществляется ядром операционной системы. Операционная система использует планировщик общего назначения для переключения между потоками. Этот универсальный планировщик не всегда очень эффективен.

Greenlets эмулируют многопоточные среды, не полагаясь на собственные возможности операционной системы. Управление гринлетами осуществляется в пространстве приложения, а не в пространстве ядра.

Надеюсь, это поможет вам понять основы. Здесь есть что исследовать, так что счастливых знакомств :)

Больше контента на plainenglish.io