Долгое время я искал элегантные решения для создания и запуска фоновых заданий в PHP.
Я присоединился к компании, которая массово использовала Laravel, а Laravel поставляет с потрясающей системой Queue. Внезапно я забыл, насколько утомительно и хлопотно было писать очереди на PHP.
Но кажется, что очередь Laravel тесно связана с Laravel. У нас заканчиваются такие элегантные решения для приложений, которые не используют фреймворк Laravel.
Бернар спешит на помощь. Bernard - мощная библиотека PHP для создания и выполнения фоновых заданий в PHP. Согласно его вступлению в репозиторий Github:
Bernard - это многофункциональная PHP-библиотека для создания фоновых заданий для последующей обработки. Бернард делает фоновую обработку на PHP очень простой и приятной.
Но настроить Бернарда непросто, а документация недостаточно ясна. Итак, это моя попытка начать настройку Бернарда.
Концепции
Сообщение
Сообщение - это объект любого класса, реализующий Bernard\Message
, который добавляется в фоновую очередь. Он представляет работу, которую нужно выполнить.
Режиссер
Производитель - это объект, который отправляет сообщение в нужную очередь.
Потребитель
Потребитель - это объект, который принимает сообщения из очереди и отправляет сообщение получателю сообщения для обработки задачи, указанной в сообщении.
Сериализатор
Сериализатор - это объект, который отвечает за:
- преобразование объекта сообщения в JSON для постоянного хранения
- преобразование JSON обратно в объект сообщения для использования сообщения Потребителем.
Водитель
Драйверы - это подключаемая система брокера сообщений, отвечающая за фактическую отправку сообщений от производителей к потребителям. В Бернарде Драйвер реализует Bernard\Driver
. Существуют различные реализации на основе Redis, RabbitMQ и т. Д. Полный список можно найти на странице драйверов в официальной документации. Вот простой пример построения драйвера на основе predis/predis
:
Простой пример
Создание сообщения
Здесь мы создали сообщение с именем SendForgotPasswordEmail
и отправили его в очередь emails
.
Потребляющее сообщение
Теперь нам нужно создать потребителя, который слушает очередь emails
.
Использование более одной очереди
Расширенный пример:
Предположим, мы хотим общаться, используя объекты сообщений нашего собственного класса следующим образом:
Все хорошо до сих пор. Но Бернарду необходимо преобразовать объект сообщения в JSON, чтобы он мог сохранить сообщение в соответствующей очереди в формате JSON. По умолчанию Бернард поддерживает только Bernard\Message\PlainMessage
.
По умолчанию Бернард может только нормализовать Bernard\Message\PlainMessage
. Нам нужно настроить настраиваемый нормализатор для нормализации нашего настраиваемого объекта.
Мы добавили новый ObjectNormalizer
, который может нормализовать любой объект. Вам необходимо установить пакет symfony/property-access
, чтобы использовать этот нормализатор.
Теперь давайте создадим класс-обработчик для обработки задачи.
Назначение вызываемого обработчика заданий для каждого класса сообщений довольно утомительно. Что, если бы мы могли создать карту класса сообщения для его класса обработчика, как показано ниже, и загрузить обработчик по запросу.
Теперь мы можем попытаться разрешить объект-обработчик из контейнера внедрения зависимости. В этом посте я предполагаю, что внедрение зависимостей реализует PSR-11 ContainerInterface
. Но приведенный ниже пример в большинстве случаев будет похож.
Теперь вот как будет выглядеть наш класс-обработчик:
Выглядит довольно чисто и, прежде всего, элегантно.
Лично я предпочитаю создавать абстрактный класс AbstractMessage
class, который возвращает имя сообщения на основе полного имени класса, как показано ниже:
Вы также можете использовать прослушиватели присоединения к EventDispatcher
в сценарии потребителя, как показано ниже:
Код окончательного результата доступен в этом репозитории.
Пожалуйста, не стесняйтесь копаться, и вы можете прокомментировать, если у вас есть лучший подход к ситуации.