Mastering Swoole PHP: Build High Performance Concurrent System with Async and Coroutines / Осваиваем Swoole PHP: построение высокопроизводительной конкурентной системы с асинхронностью и корутинами: Проблемы конкурентности

Оглавление
Английский оригинал Перевод на русский

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

Проблемы конкурентности.

У вас может возникнуть резонный вопрос: откуда же берутся проблемы конкурентности?

Kee 01.02.21 в 11:35

0

Один из главных недостатков PHP-FPM в том, что он связывает отдельное соединение с довольно тяжелым процессом, и неспособен динамически масштабироваться для обработки большего количества одновременных запросов.

Kee 01.02.21 в 11:38

0

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

Kee 01.02.21 в 11:40

0

Кроме того, представьте и 100 подключений к базе данных, поскольку открытое соединение с БД нельзя использовать повторно для других запросов.

Kee 01.02.21 в 11:40

0

В теории, если мы будем рассматривать скрипт, который всего лишь возвращает "Hello world", процесс PHP будет выполнен за предсказуемый и короткий промежуток времени. Больших проблем не предвидится, задействованы только процессорные вычисления, и результат будет получен очень быстро.

Kee 01.02.21 в 11:49

0

Но в реальности, современные веб-приложения всегда включают в себя и внешние операции ввода-вывода: они обращаются к базе данных, вызывают HTTP сервисы (к примеру, OAuth), выполняют массу дорогостоящих действий, вроде отправки почты, и так далее. Время ожидания результата внешних операций зачастую не поддаётся оценке, а по множеству причин результат может не вернуться вообще. И вот у нас куча процессов, ожидающих I/O, но не выполняющих на сервере ничего полезного.

Kee 01.02.21 в 12:01

0

Общая идея при решении проблемы конкурентности - сделать процессы асинхронными. Мы рассмотрим несколько различных способов осуществления такой возможности.

Kee 01.02.21 в 17:58

0

До того, как Swoole PHP и другие CLI фрейморки завоевали популярность, распространённым решением проблемы для отделения пользователя от внешних вызовов АПИ и запросов было использование очереди. Вам наверняка знакомы такие решения, как Redis, или очереди в базе данных из Laravel. На уровне приложения вы всего лишь помещали данные для задачи в очередь, а позже вызывали другой, фоновый процесс, который обрабатывал задачу асинхронно.

Kee 02.02.21 в 10:02

0

Вот минус такого подхода: как только вы помещали данные для задачи в очередь, в текущем запросе у вас больше не было возможности контролировать ход исполнения. Вам приходилось снова опрашивать HTTP сервер, чтобы узнать, закончено ли выполнение фоновой задачи, или ещё нет.

Kee 02.02.21 в 10:08

0

Синхронный процесс:

Рисунок 4.1 (HTTP запрос в синхронном режиме)

Это обычный случай для PHP-FPM приложений - весь процесс соединения может быть заблокирован на каждом из уровней. Все компоненты могут быть заняты, ожидая результатов от медленного внешнего поставщика данных. И общая задержка ответа на запрос с каждым медленным уровнем будет расти тоже.

Kee 02.02.21 в 10:13

0

Асинхронный процесс:

Систему, описанную чуть выше, можно улучшить, сделав запрос асинхронным. Прежде всего изменим АПИ так, чтобы он помещал задачу в очередь и возвращал подтверждение клиенту. Затем отдельными запросами будем периодически опрашивать базу данных, пока там не появится результат выполнения нашей задачи*. Процесс обработки запроса становится «черным ящиком», и больше не замедляет ту часть АПИ, которая обращена к клиенту.

--------------------
* От переводчика: при таком подходе, как правило, задачи из очереди запускаются на выполнение с помощью планировщика (например, cron).

Kee 02.02.21 в 10:23

0

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

Kee 02.02.21 в 11:37

0

Клиентская сторона, вместо того, чтобы удерживать PHP процесс и ожидать ответа на текущий запрос, получает быстрое подтверждение о том, что задача поставлена в очередь, и проверяет результат выполнения другими запросами.

Kee 02.02.21 в 11:43

0

Но проблема остаётся проблемой, ведь мы по-прежнему тратим ресурсы на дополнительные HTTP запросы, проверяя статус выполнения.

Kee 02.02.21 в 11:44

0

Есть ли лучшее решение, чем терять ресурсы на таких запросах?

Для библиотек с поддержкой мутиплексирования I/O, вроде Swoole PHP, становится возможным использование одного процесса несколькими клиентами сразу, и ожидание результата перестаёт быть большой проблемой. Для каждого клиента можно даже организовать отдельный постоянный канал через WebSocket без больших затрат памяти и без умножения процессов Linux.

Kee 02.02.21 в 11:45

0

В этом великая сила решения - клиентские I/O больше не привязаны к процессам Linux.

Kee 02.02.21 в 11:53

0

Вы можете заметить, что некоторые безсерверные сервисы, вроде AWS Lambda, до сих пор не отделяют клиентский I/O от процессов Linux. Решение не самое лучшее, и мы надеемся, что со временем они пересмотрят свой подход.

Kee 02.02.21 в 12:12

0
Минутку...