Ответы пользователя по тегу PHP
  • Как в RabbitMQ обработать все сообщения а затем удалить очередь и закрыть соединение?

    @yarkin
    Я не из мира PHP, но полагаю что можно попробовать basic_get вместо basic_consume, или попробовать опцию $nowait=true
    Ответ написан
    Комментировать
  • Как избавиться от ошибки "no free channel ids" в rabbitmq?

    @yarkin
    По PHP возможно не подскажу, но всё же в таких ситуациях желательно публиковать и пример кода. По всей видимости, открывается канал (channel) на каждую публикацию сообщения, чего делать не стоит. Каналы нужны для параллельной работы через одно TCP подключение, так как AMQP протокол по своей натуре синхронный (следующую команду нельзя послать, если ожидается ответ от предыдущей). Если через один канал скорость публикации сообщений с подтверждением не устраивает, то можно:
    • открыть несколько параллельных каналов,
    • или использовать пакетную отправку, когда подтверждение приходит на каждые N запросов.
    Ответ написан
  • RabbitMQ: как правильно выполнять тяжелые задачи?

    @yarkin
    Была подобная проблема, сишный клиент в один поток не умел нормально в heartbeat. При отключении heartbeat'ов на уровне AMQP протокола были проблемы с "зависшими клиентами" на стороне RabbitMQ, когда приложение выходило непредвиденно. Настройка TCP keepalive помогла решить данную проблему.
    Не знаю точно как работает современный php, но, если есть возможность держать отдельный поток для поддержания AMQP коннекта с включённым heartbeat'ом, то это будет лучше, чем через TCP keepalive. Отсылать ack обратно лучше всё же после завершения обработки задачи.
    Ответ написан
    Комментировать
  • Как организовать очередь сообщений так, что бы каждое след. сообщение передавалось только после того, как обработано предыдущее?

    @yarkin
    Из текста не до конца понятно, Вы хотите, чтобы была очередь или sender должен выполняться каждый раз для нового сообщения? Если очередь, то обрабатывать сообщения по одному можно, но только если получатель один. В протоколе AMQP можно вручную получать сообщения по одному - basic_get, или выставить количество неподтвержденных сообщений в 1 и подтверждать обработку каждого.
    Ответ написан
    Комментировать
  • Типы обменников в rabbitmq и хранение сообщения при неактивном получателе?

    @yarkin
    Если Вы хотите на пустом RabbitMQ создать обменник, кинуть в него сообщения и позже подключить очереди к этому обменнику в надежде получить ранее отправленные сообщения, то это у Вас не получиться. Обменник не хранит сообщения, а разбрасывает входящие сразу по мере их получения, если в данный момент у него нет очередей для отправки - сообщение просто отбрасывается. Вам нужно стартовать потребителей до того, как отправлять сообщения. Если хотите, чтобы в момент, когда потребитель отвалился, сообщения накапливались, то надо сделать предсказуемое/известное для потребителя имя очереди (по необходимости сделать её durable).
    Если надо, чтобы при старте RabbitMQ что-то создавало очереди и обменники, то через менеджмент плагин такое можно устроить (говорят, в последних версиях даже можно это сделать без менеджмент плагина).
    Ответ написан
  • Как аутентифицировать пользователя приложения при подключении к RabbitMQ по протоколу WEB-STOMP?

    @yarkin
    Boris Korobkov дал ценное замечание по поводу того, что всем должен рулить сервер и нужно добавить элемент случайности в имена, дополню его несколькими рекомендациями.

    1) Если очередь будет создана сервером, то auto-delete не будет работать, если клиент не подпишется на неё.
    2) Не забывайте, что если два клиента (например, две вкладки или две сессии одного пользователя) подключатся к одной очереди, то сообщение получит только один из них. В своих решениях я использовал подход, что очередь создавалась клиентом, а обменник сервером, но необходимо убедиться, что до RabbitMQ доходят только легитимные запросы (от авторизованных клиентов) и пользователь ограничен в правах создавать только нужные очереди и подписывать их на нужные обменники.
    3) Рекомендовал бы не выставлять порт web-stomp плагина без доп.защиты (например, HAProxy), которая позволит защитить RabbitMQ от перегрузки подключениями.

    P.S. Писал статью на Хабр год назад о подобной системе, может быть что-то будет интересное в ней ещё - https://habr.com/post/341068/
    Ответ написан
  • RabbitMQ: Как получить только часть сообщений?

    @yarkin
    1) Использовать basic_get вместо basic_consume, эта штука получает всего лишь одно сообщение за вызов, пример использования - https://github.com/php-amqplib/php-amqplib/blob/ma...
    2) Сделать счётчик полученных сообщений и при достижении 10 закрыть канал.
    Ответ написан
  • RabbitMQ: Как сохранить сообщение в очереди?

    @yarkin
    Если я понимаю верно, то при создании очереди (queue_declare) в качестве имени указывается пустая строка, на что RabbitMQ создаёт для неё случайное имя и добавляет флаг exclusive, вследствие чего очередь удаляется при закрытии подключения клиентом. Попробуйте дать собственное имя для очереди и посмотрите параметры вызова этого метода.
    Ответ написан
  • Как отследить завершение очереди RabbitMQ?

    @yarkin
    Если хочется реализовать всё через очередь, где каждый элемент это товар, то как вариант создать временную очередь, заполнить её новыми товарами, а потом сообщить дальше её имя. Если интересно уведомление о завершении импорта также получить через RMQ, можно создать обменник, а основной процесс создаёт себе служебную очередь и подписывается на этот обменник.
    Но, имхо, если импорт происходит в одном процессе, а генерация кэша по одному элементу это очень дешёвая операция, то вероятно не очень эффективно размещать каждый товар отдельно, лучше складывать их пачками, чтобы также пачку и обработать.
    Ответ написан
  • Как правильно организовать отказоустойчивость при работе к кластером RabbitMQ?

    @yarkin
    На уровне данных. Когда поднимается ResplicaSet в MongoDB, она понимает, что данные нужно дублировать на несколько нод. Когда создаётся кластер RabbitMQ (по факту это кластер Erlang-машин), то по всем машинам дублируются лишь метаданные (информация об обменниках, очередях и т.п.), но сами данные остаются жить на одной ноде (но прозрачно передаются/забираются, если клиент подключён к другой ноде кластера). У них есть статья в доке по отказоустойчивости к потери данных.

    На уровне коннектов. Драйвер MongoDB открывает подключения до каждой ноды ReplSet (может быть лишь до какого-то их количества, не уверен точно) и, в зависимости от операции и её параметров, использует то или иное подключение. То есть поддержка ReplSet заложена на уровне драйвера. RabbitMQ работает на протоколе AMQP (нативный), который работает только с одной нодой брокера, скорее всего есть куча библиотек, которые обёртывают в себе подключение к нескольким серверам RabbitMQ (либо один коннект и другой поднимается по отказу первого, либо сразу несколько коннектов, которые дают балансировку и малый лаг при отказе одной ноды). Но, если нет либы для работы с несколькими нодами, то сделать её, думаю, особых проблем не составит.
    Ответ написан
    Комментировать