Как стать автором
Обновить

Пример своего транспорта для Symfony Messenger

Уровень сложностиПростой
Время на прочтение3 мин
Количество просмотров923
Сравнительное тестирование транспорта сообщений для Symfony Messenger.
Сравнительное тестирование транспорта сообщений для Symfony Messenger.

Предыстория

В процессе изучения Symfony Messenger мной было создано два самодостаточных примера, демонстрирующих его работу:
https://habr.com/ru/articles/817425/ - Symfony Messenger и Symfony Console
https://habr.com/ru/articles/819187/ - Symfony Messenger и Workerman

В каждом из этих учебных примеров в качестве транспорта сообщений для простоты была выбрана БД SQLite (для понимания работы Symfony Messenger мне совершенно не хотелось возиться с установкой Redis, RabbitMQ или Mongo).
Готовой реализации транспорта именно для SQLite я не нашёл и пришлось её использовать через DBAL Doctrine (https://github.com/symfony/doctrine-messenger).

И всё бы ничего, но внутренний перфекционист :-) нашёптывал, что использование целой Доктрины лишь для того, чтобы работать с одной-единственной таблицей с очередями сообщений — это явный перебор…

Бороться с затерроризировавшим меня внутренним перфекционистом ;-) я не стал и, решив поглубже разобраться с устройством транспорта сообщений в Symfony Messenger, создал такой транспорт для SQLite сам, с использованием PDO.
Также было произведено тестирование производительности этого моего решения и решения на Doctrine с БД на жёстком диске и на RAM диске.

SQLite транспорт для Symfony Messenger: где взять, пример использования

SQLite транспорт на основе PDO для Symfony Messenger

SQLite транспорт сообщений на основе PDO можно взять отсюда: https://github.com/balpom/sql-messenger

На самом деле, я немного смухлевал ;-) и с нуля ничего не писал, а просто переделал Doctrine Transport, упростив всё, что только можно.

Так как для работы с SQLite используется PDO, то, скорее всего, после некоторой доработки напильником эту мою поделку можно будет использовать и со всеми остальными БД, которые поддерживает PDO.

Пример использования SQLite транспорта на основе PDO для Symfony Messenger

Пример использования SQLite транспорта сообщений можно взять отсюда: https://github.com/balpom/symfony-messenger-sqlite

Либо можно установить через Composer:
composer create balpom/symfony-messenger-sqlite

Как запустить пример

Подробно расписывал в статье https://habr.com/ru/articles/817425/, здесь пробегусь по минимуму.

Запуск Worker’а (имитирует отправку SMS):
php bin/console messenger:consume sql-async
(В конце именно sql-async, а не doctrine-async.)

Добавление сообщений в очередь (открывать в отдельной консоли):
php tests/send.php

Мягкая остановка Worker’ов:
php bin/console messenger:stop-workers

Сравнительное тестирование SQLite транспорта для Symfony Messenger

Для эксперимента были сделаны две отдельные инсталляции двух примеров:
https://github.com/balpom/symfony-messenger-sample — Doctrine transport
https://github.com/balpom/symfony-messenger-sqlite — мой самодельный транспорт

Для тестирования производительности был создан простой скрипт tests/addtime.php, добавляющий в очередь заданное количество сообщений и замеряющий истраченное время (добавлен в вышеуказанные примеры).

$message = 'Simple message';
$total = 1000;
echo 'Start ' . $total . ' messages adding...' . PHP_EOL;
$start = microtime(true);
for ($i = 1; $i <= $total; $i++) {
    $sms = new SmsNotification($message);
    $bus->dispatch($sms, [new BusNameStamp($busName)]);
}
echo (microtime(true) - $start) . ' sec' . PHP_EOL;

Тестирование проводилось для БД SQLite, размещённых на жёстком диске и на RAM-диске.
Использовалось различное число сообщений. Для чистоты эксперимента перед каждым замером «старая» база удалялась.

Процессор — старый добрый Xeon X5650 (6x2,67GHz HT) LGA1366.

Результаты тестирования doctrine-messenger и sql-messenger.
Результаты тестирования doctrine-messenger и sql-messenger.

Как видно, 1000 сообщений в очередь на жёстком диске мой транспорт добавляет за ~68 секунд, а Doctrine transport - за ~152 секунды. Разница в ~2.2 раза! Вообще, думал будет процентов 15-20...

На RAM-диске — да, всё летает. :-) Те же 1000 сообщений добавляются за 0.16 и 0.31 сек соответственно. Миллион - за 146 и 269 секунд соответственно.

Что интересно - база на миллион сообщений, созданная Doctrine, почему-то на ~0.3% больше базы, созданной моей поделкой.

Размеры баз, созданных sql-messenger и doctrine-messenger.
Размеры баз, созданных sql-messenger и doctrine-messenger.

Послесловие

Ну не знаю… Было интересно повнимательнее посмотреть и почувствовать, как оно там внутри Symfony Messenger устроено и данный опыт, безусловно, очень полезен.
Матёрые PHP профи почти наверняка найдут кучу изъянов в моём коде — ну и ладно...

Догадывался, что SQLite на жёстком диске будет тормозить, но не думал, что настолько: 1000 сообщений за 68 секунд — это ~15 сообщений в секунду.
Про Doctrine с её ~6.5 сообщений в секунду я вообще молчу...
Интересно, а MySQL как проявляет себя в очереди?

Да, получается, что на RAM-диске SQLite быстрее в ~400-500 раз (ну да, RAM-диск всё-таки :-) ).

В-общем, очевидно, что практическое применение SQLite в качестве хранилища очередей крайне ограничено какими-то простыми или учебными задачами.

Хотя… ;-)

Теги:
Хабы:
Если эта публикация вас вдохновила и вы хотите поддержать автора — не стесняйтесь нажать на кнопку
+4
Комментарии0

Публикации

Истории

Работа

Ближайшие события

AdIndex City Conference 2024
Дата26 июня
Время09:30
Место
Москва
Summer Merge
Дата28 – 30 июня
Время11:00
Место
Ульяновская область