Вступление
Сейчас наверное многие подумают, что это кликбейт статья, но это не так, далее я поделюсь своим опытом как получить результат в заголовке.
Суть проблемы
Инженеры которые сталкивались с поддержкой Matomo знают, что выжать из нее более 400-500 rps без плагина QueuedTracking практически не реально. Но и с плагином потолок производительности поднимается не сильно высоко, где-то до 1100-1200 rps. Даже если вы видите только 200-е ответы и большие значения в мониторинге php-fpm, реальный rps будет в мониторинге Redis, а именно команды rpush, остальные процессы php-fpm просто умирают по timeout. Соответственно эти данные отслеживания просто теряются.
У меня же пиковые значения были около 2000 rps и в итоге терялось около 18% трафика. Это много, очень много. Я не буду описывать весь мой тернистый путь к данному решению, просто перейду сразу к нему.
Мой вариант решения проблемы с обработкой высокого трафика
Я решил исключить плагин QueuedTracking из процесса доставки аналитики до Redis. Но из Redis в БД данные выгружает плагин, соответственно мне нужно было написать свой api, который будет принимать трафик, парсить его и сохранять в Redis, в том формате в котором это делает плагин. При этом решается одна из основных проблем, все активные процессы php-fpm держат соединение до БД и при этом еще от них есть трафик, они проверяют доступность БД и получают настройки, а это получается 1000+ подключений к БД. Это очень плохо для БД, поддержание такого количества подключений, требует много ресурсов CPU, в моем случае это были бы "too many connections".
Так как у меня есть некоторые познания и опыт в написании приложений на .net, его я и выбрал. В процессе мозгового штурма я решил разделить доставку на 2 этапа:
Первый api + producer с минимальным количеством кода, принимает аналитику (url path и нужные заголовки) сериализует в json и отправляем в очередь на RabbitMQ. В результате 1 экземпляр приложения уже выдает 7к+ rps
Второй это consumer из очереди RabbitMQ и producer в очереди Redis. Тут мы парсим url path и формируем json понятный плагину QueuedTracking, а rps получаем 3к и разницу в rps компенсируем количеством consumer'ов, я сделал 3.
Да есть нюансы: настройки необходимо менять в 3-х компонентах, а не в одном, но результат того стоит. И, конечно же, при обновлениях необходимы дополнительные тесты.
Бонусом получаем малое количество подключений к БД (количество воркеров плагина + подключения с front'а)
Думаю у многих сразу возникает вопрос, а как все эти данные отправить в БД за вменяемые сроки? Если учесть, что скорость выгрузки 16 воркеров (а это максимальное количество) плагина около 3к rps и это если позволяет производительность БД! Об этом я с удовольствием расскажу в следующей статье, если сообществу эта тема будет интересна.
Шпаргалка как посмотреть содержимое в очереди Redis
Можно конечно воспользоваться командой на ноде Matomo:
./console queuedtracking:print-queued-requests --queue-id={Номер очереди}
Но это будет php объект, а нам нужен json
Поэтому подключаемся к Redis и приступаем:
select {Номер Бд} - выбираем нужную БД
lrange trackingQueueV1_{Номер очереди} 0 1 - получаем 1 сообщение
ltrim trackingQueueV1_{Номер очереди} 0 -1 - удаляем все сообщения в очереди
И мы увидим не читаемую абракадабру, точнее сжатое сообщение. Чтобы это исправить идем в /{dir_matomo}/plugins/QueuedTracking/Queue/Backend/Redis.php, нам нужна строка 103:
Matomo будет нормально читать как сжатые, так и не сжатые сообщения.
Шпаргалка актуальна для версии плагина 4.0.7
Спасибо за внимание! Критика, вопросы и пожелания приветствуются в комментариях!