Что такое очереди сообщений (message queues)?

Ответ

Очередь сообщений — это компонент архитектуры, обеспечивающий асинхронную связь между сервисами. Отправитель (producer) помещает сообщение в очередь, не дожидаясь его обработки. Получатель (consumer) извлекает и обрабатывает сообщение позже, независимо от отправителя.

Ключевые преимущества:

  • Развязка компонентов: Сервисы не зависят от доступности друг друга.
  • Гарантированная доставка: Сообщения сохраняются до обработки.
  • Балансировка нагрузки: Можно масштабировать количество потребителей для обработки пиков.
  • Отказоустойчивость: Сообщения не теряются при сбое потребителя.

Популярные реализации: RabbitMQ (AMQP), Apache Kafka (логи), AWS SQS, Redis (через списки).

Типичный сценарий использования — фоновая обработка задач:

// Producer: Веб-приложение ставит задачу на отправку email в очередь
$connection = new AMQPStreamConnection('rabbitmq', 5672, 'user', 'pass');
$channel = $connection->channel();
$channel->queue_declare('email_tasks', false, true, false, false);

$emailData = json_encode(['to' => 'user@example.com', 'template' => 'welcome']);
$msg = new AMQPMessage($emailData, ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]);
$channel->basic_publish($msg, '', 'email_tasks');

// Consumer: Отдельный worker-процесс слушает очередь и отправляет письма
$callback = function ($msg) {
    $data = json_decode($msg->body, true);
    // Логика отправки email через SMTP или сторонний API
    sendEmail($data['to'], $data['template']);
    $msg->ack(); // Подтверждаем успешную обработку
};
$channel->basic_consume('email_tasks', '', false, false, false, false, $callback);
while ($channel->is_open()) {
    $channel->wait();
}

Ответ 18+ 🔞

Слушай, а вот эти ваши очереди сообщений — это же просто гениальная штука, ёпта. Представь себе: один сервис кидает задачу в ящик и дальше по своим делам пошёл, ему похуй. А другой сервис, когда проснётся или освободится, достаёт эту задачу и делает своё дело. Никто никого не ждёт, все довольны. Красота, ядрёна вошь!

Зачем это вообще нужно, спросишь? Да всё просто, как три копейки:

  • Развязка, блядь: Сервисы живут своей жизнью. Если получатель лег, отправитель может дальше спокойно кидать сообщения в очередь — они никуда не денутся. Никакой этой синхронной ебалы, когда всё встаёт колом из-за одного тормоза.
  • Гарантия, что дойдёт: Сообщение ляжет в надёжное хранилище и будет там лежать, пока его не заберут. Не потеряется, даже если всё вокруг накрылось медным тазом.
  • Распределение нагрузки: Навалилась овердохуища работы? Запусти ещё десять воркеров-потребителей, пусть дружно жрут из очереди. Балансировка на раз-два.
  • Живучесть: Потребитель упал — и хуй с ним. Сообщения в очереди, поднимут его — он с того же места и продолжит.

Из чего выбирать-то? Да вариантов — хоть завались. Старый добрый RabbitMQ (классика жанра), Apache Kafka (для логов и ивентов — просто зверь), облачные штуки вроде AWS SQS, или даже Redis, если задачи простые и недолгие.

Где это применяется? Да везде, где можно отложить работу! Самый хрестоматийный пример — отправка писем. Смотри, как это выглядит в коде, тут всё наглядно:

// Producer: Твой веб-приложение, которое только что зарегистрировало пользователя.
// Ему нужно отправить приветственное письмо, но делать это прямо сейчас — долго и рисково.
// Поэтому оно просто пихает задание в очередь и забывает.
$connection = new AMQPStreamConnection('rabbitmq', 5672, 'user', 'pass');
$channel = $connection->channel();
$channel->queue_declare('email_tasks', false, true, false, false);

$emailData = json_encode(['to' => 'user@example.com', 'template' => 'welcome']);
$msg = new AMQPMessage($emailData, ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]);
$channel->basic_publish($msg, '', 'email_tasks');

// Consumer: Где-то на другом конце света (или просто в другом процессе) воркер дежурит.
// Он тупо слушает очередь и, как только видит задание, выполняет его.
$callback = function ($msg) {
    $data = json_decode($msg->body, true);
    // Вот тут уже реальная, возможно, долгая работа: коннект к SMTP, рендер шаблона.
    sendEmail($data['to'], $data['template']);
    $msg->ack(); // Всё, готово, можно сообщение из очереди нахуй удалять.
};
$channel->basic_consume('email_tasks', '', false, false, false, false, $callback);
while ($channel->is_open()) {
    $channel->wait(); // Сидит себе, ждёт, как кот у мышиной норы.
}

Вот и вся магия. Веб-сервер не бздит, что почтовик тормозит, пользователь не видит ошибок, а письма всё равно улетают. Архитектура, блядь, в кайф.