Увидев вводный пост про AMQP решил поделиться своей практикой использования этого механизма.
Ещё задолго до начала внедрения AMQP у нас был полный зоопарк из различных обработчиков фоновых задач: delayed_job , starling + workling и т.п. Плюс к этому, ещё активно использовался HTTP ping между серверами и juggernaut для пуш-канала на браузер. Ах, ещё забыл брутальное оповещение по IP multicast.
Весь этот перечень страшных слов работает, но уж очень он разнообразен и обширен, решили урезать. Чего же общего между HTTP ping-ом и старлингом? Да то, что это всё сообщения от источника к подписчикам. AMPQ был выбран как общий транспорт для таких сообщений.
AMQP — транспорт по доставке сообщений от источника (producer) к потребителю (consumer) через брокер. В брокере есть точки входа, к которым цепляются источники (точки обмена, exchanges) и точки выхода, очереди (queues), к которым цепляются потребители. Точки входа соединяются с очередями с помощью bindings — соединений. Об организации внутри брокера ниже поподробнее.
Важно отметить, что протокол AMQP по своей организации асинхронный и рассчитан на организацию consumer-а (потребителя) в event based стиле. Т.е. если у вас многонитевой потребитель, который обрабатывает задачи, у вас будет куча проблем: AMQP на это плохо рассчитан.
У каждого AMQP сообщения есть канал по которому оно передается (для мультиплексирования внутри одного TCP соединения). Ответы на запросы могут прийти когда угодно. Потребитель стоит писать с использованием EventMachine, libev или чего-то похожего.
Это очень важно, потому как иначе, если вы напишете:
declare_queue(..)
bind_queue(..)
Брокер сразу был выбран RabbitMQ по той причине, что он конфигов не имел, а ApacheMQ имел энтерпрайзного вида многокилобайтное XML-ное полотно, в котором ни один пункт нам не понадобился. Нам, как знатным макоёводам первый выбор понравился гораздо больше и пока не жалели.
Надо сразу отметить, что ApacheMQ выглядит более обширной реализацией, но в нём нет поддержки протокола AMQP (да и вообще у них на сайте создается впечатление, что они к AMQP никакого отношения не имеют). Зато у RabbitMQ есть экспериментальная поддержка протокола Stomp, который есть и у ApacheMQ. Впрочем, мы остановились на хождении по AMQP, потому что для рельсов есть прекрасная реализация написанная Аманом Гуптой. Не, честно, индус, а хорошо написал. Почти не пришлось допиливать.
Такого же удобного способа складывать задачи в AMQP, как в Delayed Job (UserMailer.send_later(:deliver_register_confirmation, user)) мы ещё не нашли, но просто руки ещё не дошли. В источнике сообщений вполне можно использовать синхронную реализацию протокола AMQP, потому что задача источника плюнуть сообщением и забыть про него. Учитывая, что это зачастую веб-сервер, ждать точно ничего не надо.
AMQP — не просто FIFO канал. Точки входа (exchanges) могут быть разных типов и каждый тип обуславливает правила доставки сообщений по присоединенным очередям.
Так же вы можете играть настройками персистентности (как это слово перевести?) очередей, точек обмена и сообщений.
В упомянутой в заголовке статье уже рассказаны особенности разных типов exchange, так что я лучше расскажу про пример использования.
Важно, что очередь одна, а потребителей из неё много, причем всё персистентное. Каждое сообщение либо останется в очереди, либо достанется одному и только одному фоновому демону.
Классический пример для передачи сообщений — работа онлайн-чата (Juggernaut). Для упрощения, положим что Flash-клиенты цепляются сразу к AMQP брокеру (хотя на самом деле вы не должны хотеть этого).
Я привел лишь пару практических примеров использования AMQP. Сам протокол подразумевает гораздо более широкое использование (вплоть до передачи файлов), однако нам оно просто ещё не было нужно.
Сам транспорт работает надежно и пока у нас нареканий на качество AMQP как стандарта и RabbitMQ как реализации ещё не было. Все клиентские либы требовали хоть какого-то, но допиливания.
RabbitMQ основным протоколом предлагает AMQP и в качестве экспериментальных реализаций предлагает Stomp, email, REST, XMPP (джаббер).
ApacheMQ предлагает OpenWire и Stomp. AMQP я там не нашел, а самый хороший рельсовый клиент для ActiveMQ был именно для AMQP. Плюс C-шную библиотеку от RabbitMQ оказалось проще всего перевести на libev. Это подтолкнуло к выбору RabbitMQ.
Начну с конца: я бы закладывался на 0.8. Реализации есть, работают, хлеба не просят. 1.0 в данный момент в состоянии драфта. Честно говоря глубоко и детально в спецификацию 1.0 я не вчитывался — лишь проглядел её. У меня, учитывая то, что и 0.8 мне за глаза, возникло ощущение: понахреновертили.
Наверное, AMQP становится безумно крут, когда сам начинаешь писать свои эксченджи для кастомных задач и гонять весь трафик через него. Но я лучше пошлю файл через nginx, чем через ActiveMQ брокер. У авторов стандарта наверное другие задачи и условия.
Резюме такое: я бы не стал связываться с драфтовым 1.0, который ещё не реализован по причине отсутствия самого стандарта.
crosspost: на хабрахабре