Pull to refresh

Comments 13

сборщик мусора для чистки ссылок

Вот тут по подробнее, зачем? Во первых просто для ссылок php и так почистит тогда когда надо, в прочем как и для циклических ссылок. Раскройте цель подобных манипуляций со сборщиком подробнее. Есть мнение что это как-то связано с


постоянно копить в нем ссылки и держать соединение с бд — это плохо.

как я уже говорил — php сам удалит ссылки. Более того вызов gc_collect_cycle вообще ничего не сделает особо.


Зато другая проблема появляется — reset менеджера при исключениях. И вот там вполне коннекшен умирает и его надо передернуть. А закрывать коннекшен между задачами в очереди — крайне неразумно. Скажем для postgresql реконнект штука относительно дорогая, да и зачем нам этот оверхэд по времени обработки сообщений..

gc_collect_cycle бесполезен, подтверждаю. А вот вызов gc_mem_caches стоит делать — иначе php не отдаёт память системе — это может быть критично если размер заданий плавает и на некоторых потребление памяти сильно больше среднего.

Вот тут я уже не знаю точно, но насколько я помню менеджер памяти не просто так не высвобождает запрошенные у системы блоки, а потому что планирует реюзать их далее. То есть если приложению вдруг понадобилось 200 метров, то почему бы ему еще раз не понадобилось?


Ну то есть я к тому что часто ее вызывать наверное тоже не стоит как минимум потому что иначе это будет вынуждать пых чаще просить систему выделять память. Но периодически, скажем раз в 100 сообщений или в зависимости от потребления памяти — пожалуй стоит.

Разве rabbitmq:consumer работает в режиме демона? Мне казалось, что обычное CLI приложение.

Ну в целом все упирается в то что считать "режимом демона". Эта команда — обычное CLI приложение, которое не умирает после первого сообщения и умеет ловить/обрабатывать сигналы (пока только stop, в restart написан TODO: implement). Далее вопрос как запускать.

Позвольте дополнить самую последнюю фразу «Проблемы будут всегда.» данной статьи.

О некоторых багах phpamqp-lib. Баг репорты есть на гитхабе, до сих пор нету решения.
1. Consumer: допустим запустили мы consumer и активировали heartbeat. От тихо ожидает новых сообщений в этой точке github.com/php-amqplib/RabbitMqBundle/blob/master/RabbitMq/BaseConsumer.php#L53. Бесконечно долго, т.к. timeout = 0. Допустим, падает сетевое соединение на какое-то время, затем оно восстанавливается. Консьюмер по прежднему ждёт сообщения в той точке, а RabbitMQ уже закрыл соединение. Всё, консьюмер будет висеть в памяти до тех пор, пока его не прибьют сигналом каким-нибудь. Соответсвенно, если в консьюмере есть таймер для «самоубийства», то он не сработает.

2. Без heartbeat могут быть проблемы с незакрытыми соединениями на стороне RabbitMQ. Возможно тут ещё всему виной HAProxy, который в нашем случае стоит перед кластером RabbitMQ.

Из-за этих казалось бы незначительных проблем, код надёжного консьюмера выглядит как бесконечный try/catch и while loops, чтобы консьюмер мог реагировать на разрыв соединения и переподключаться. Такого функционала нету ни в какой высокоуровневой библиотеке (см. Enqueue, например, или бандл, описанный в данной статье)

Далее, есть очень хорошая инициатива — github.com/queue-interop/queue-interop — при помощи данных интерфейсов можно быть независимым от конкретной библиотеки, которая реализует AMQP протокол (phpamqp-lib, php extension, bunny lib). Интерфейсы позаимстованны из мира Java. Но они тоже на начальном этапе своего существования.

Например, в нашем проекты мы решили стать менее зависимыми от конкретной AMQP библиотеки. Посему перевели всех наших consumer/producer на github.com/php-enqueue/enqueue-dev. Проект не на Symfony, поэтому используем только имплементацию Queue Interop интерфейсов с использованием phpamqp-lib, чтобы в ближайшем будущем попробовать имплементацию от bunny lib.

Но тут ждало разочарование: такая фича, как Publisher Confirms, которая есть только в RabbitMQ, отсутсвует out-of-the-box в самих интерфейсах от Queue Interop (тикет на гитхабе есть). Пришлось делать костыли, очень нехорошие костыли. В проекте у нас договорённость о at-least-once delivery, потому и нужен Publisher Confirms.

Если всё подытожить, то вот мои рекомендации:
1. Подумайте 10 раз, нужин ли вам Message Broker вообще. Если можно, используйте MySQL/файлы/что угодно, что уже есть в вашем проекте. Тех поддержка самого RabbitMQ в продакшене — тот ещё геморой для Operations Team.
2. Если всё же решились на Message Broker, то ответьте на вопрос, можете ли вы потерять пару сообщений? Если можете — то используйте любые бандлы/библиотеки. В противном случае крайне рекомендую сначала написать пару consumer/producer на низком уровне (к примеру, используя phpamqp-lib без обёрток) и хорошенько пройдитесь отладчиком, разрывая соединение/физически отключая/аварийно выключая RabbitMQ. Вы удивитесь, как легко можно потерять сообщения. А уже потом подбирайте конкретные высокоуровневые бандлы под свои нужды.
Но тут ждало разочарование: такая фича, как Publisher Confirms, которая есть только в RabbitMQ, отсутсвует out-of-the-box в самих интерфейсах от Queue Interop (тикет на гитхабе есть). Пришлось делать костыли, очень нехорошие костыли. В проекте у нас договорённость о at-least-once delivery, потому и нужен Publisher Confirms.


Я думаю что Publisher Confirms не про at-least-once delivery. Это расширение дает возможность отправителю получать уведомления когда его сообщения обработаны получателем.

В документации ничего не сказано про случай когда соединение с получателем обрывается (по причине исключения например) и брокер возвращает сообщение в очередь с пометкой redelivered. Есть шанс обработать сообщение больше чем один раз. Уверен есть и другие ситуации.

Если бы мне нужно было «at-least-once delivery» я бы делал это на стороне получателя + хранилище для проверки на повтор.

От отправителя требуется проставить уникальный идентификатор сообщению.

Рекомендую посмотреть в сторону EnqueueBundle. Более мощное решение как по части использования так и по колличесту фишек для программистов. Кто много работал с RabbitMqBundle — меня поймет. Код получается проще и лаконичнее. Сравнение можно посмотреть тут. Работает не только с php-amqplib но и bunny, amqp-ext (спасибо amqp interop).

Практически все что вы описываете, в Enqueue уже реализовано из коробки: например, такие веши как, переподключение к базе данных, чистка entity manager, повторы с задержкой, RPC.

EnqueueBundle умеет это делать из коробки.

коммуникацию между компонентами через AMQP, как красиво делать RPC, то я сам чего-то подобного очень давно жду на хабре…


Вот Message bus to every PHP application

А почему не Bernard? Как мне кажется он лучше поддерживается.

Не согласен. Вот активность по enqueue репозиторию и такая же для bernard.

По фичам и коллисеству поддерживаемых брокеров отрыв так же сущесветнный.

Пользуюсь бернардом уже год, новые проекты переводим на enqueue. Он удобнее и больше полезных фич из коробки.

У меня бернард на 3 проектах, когда выбирал что ставить то больше внимания обратил на количество звезд на гитхабе. Но в будущем попробую enqueue. Спасибо.

обратил на количество звезд на гитхабе.

я то же на это купился, плюсь понравилось то о чем общаются люди в ишус трекере. Но вот прошел год и воз и поныне там. 1.0.0 все еще в альфе.

Sign up to leave a comment.

Articles