Асинхронный PHP - конспект доклада с PHP Russia 2019

17 May 2019

Всем привет! Сегодня я в Москве на конференции PHP Russia 2019. Представляю вашему вниманию краткий конспект докалада "Асинхронный PHP". Автор доклада - Антона Шабовта из компании Onliner.

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

Блокирующие операции

К блокирующим операциям относятся:

  • Работа с базами данных
  • I/O операции
  • Процессы @todo
  • Stdin/Stdout
  • Sleep и т.д.

Для асинхронной работы с БД можно попробовать реализовать асинхронный SQL клиент. Автор приводит пример SQL клиента с мспользованием сокетов.

Одной из основных концепций асинхронности являются promise. Promise предполагает отложенную операцию, по которой пока нет результата, зато есть success(onResolve) и fail(onReject) callback. В дополнение к promise вводится класс Defered, который посути является фабрикой для promise.

Для обработки Promise используется EventLoop. Можно перевести как цикл событий. Event loop используется для обработки сообщений в асинхронной среде.

Клиент в цикле запрашивает у event loop результаты promise. Если promise уже отработал, клиент получает результат выполнения. В противном случае клиент продолжает запрашивать результат у event loop.

Реализации Event Loop в PHP

  • React PHP - использует механизм Promise A, требует PHP 5.3+.
  • AMPHP - использует cooroutines, Требует PHP 7.0
  • Swoogle - интересная, но не совсем понятная китайская библиотека

ReactPHP активно использует promises и соответственно, success/fail calback. При использовании ReactPHP довольно легко нарваться на callback/promises hell. Например, если нужно сделать promise, за ним еще promise и потом еще promise.

AMPHP использует cooroutines в связке с yield(генераторы). Генераторы в свою очередь реализуют Iterable интерфейс. В генератор соответственно можно отправлять данные и передавать ошибки. Cooroutine представляет собой сопрограмму.

Кооперативная многозадачность

В результате приходим к понятию кооперативной многозадачности. В обычной ситуацииоперации в запросе выполняются последовательно. При этом возникает ситуация, что блокирующие операции занимают относительно много времени и блокируют поток. В случае с асинхронным PHP можно "склеить" выполнение нескольких запросов и, грубо говоря, во время блокировки делать что-то еще. Подобный подход используется во многих продуктах, таких, как nginx, redis, memcached и nodejs.

Обработка запроса в PHP

Обработка запроса в php происходит примерно таким образом: Входные данные попадают на nginx в котором event loop реализован. Затем запрос распределяется между пулом php-fpm процессов. При этом их количество конечно и потенциально может стать узким местом. При этом каждый новый запрос обрабатывается с чистого листа, что добавляет свои особенности.

Преимущества:

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

Недостатки:

  • Ограниченное количество процессов
  • Затраты на Context Switch

Асинхронный HTTP сервер на PHP

Следующим шагом к асинхроности будет написание своего асинхронного HTTP сервера на PHP. Основные задачи сервера:

  • Bootstrap приложения
  • Создание socket pull
  • Обработка процессов
  • Запуск сервера

Проблемы

В связи с асинхронностью возникает довольно много проблем разной степени серьезности:

  • Отсутствие стандартов(Promice A+ on Guzzle, ReactPHP, AMPHP)
  • Утечки памяти. Можно находить и устранять с помощью xdebug, strase.
  • Блокирующие операции
  • Поддержка библиотек
  • Проблемы с указанием типа

Что нас ждет в PHP 8

Возможно, Event Loop в ядре PHP и появление функции await. Возможно, появление Generic и решение проблемы с указанием возвращаемого типа.

Зачем?

Скорость, производительность. Возможно увеличение производительности в несколько раз. В то же время,есть довольно много проблем. И, возможно, такие задачи стоит решать не на PHP.

Заключение

Это был мой конспект, который я сделал в блиц режиме прямо на конференции. Тут могут быть ошибки или неточности. В будущем постараюсь их исправить. Доклад мне показался весьма интересным, правда использовать асинхронный PHP лично я наверное пока не готов. Хочу сказать спасибо докладчику Антону Шабовта и оргкомитету PHPRussia 2019. На этом пока все. Спасибо за внимание!