Pull to refresh

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

Level of difficultyEasy
Reading time3 min
Views1.4K
Сравнительное тестирование транспорта сообщений для 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 в качестве хранилища очередей крайне ограничено какими-то простыми или учебными задачами.

Хотя… ;-)

Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
Total votes 5: ↑4 and ↓1+6
Comments0

Articles