Когда я только начал планировать эту статью, я думал, что опишу различия между протоколами AMQP и HTTP, подробно расскажу про все заголовки и зачем они нужны, и как устроены потоки передаваемых сообщений и пакетов, и прочее, и прочее, и прочее… А потом я понял, что всё это уже написали до меня. Кому надо узнать справочную информацию о протоколах, может просто погуглить. А если вы надеетесь получить эти базовые знания из этой статьи, дайте-ка я нагуглю их за вас: AMQP, HTTP. А вот если вас интересует разбор реальных случаев применения AMQP и HTTP и аргументы за и против каждого протокола, то вы пришли по адресу.
Как мы столкнулись с AMQP
Недавно мы в Live and Dev начали переводить крупный монолитный проект по электронной коммерции на микросервисы, и нам нужно было придумать, как синхронизировать данные между ядром и регионами. Ядро — это место, где расположена центральная база данных и часть проекта, отвечающая собственно за онлайн-торговлю. Регионы — это части света, где находятся компоненты (Европа, Америка, Азия). Проекту идеально подошел шаблон издатель-подписчик, потому что все данные, которые требовалось синхронизировать, всегда передаются в одном направлении. При этом шаблон позволяет менять направление и сделать подписчика издателем новых данных. То есть в случае, если в будущем возникнет нужна организовать синхронизацию в двух направлениях, такая возможность у нас есть.
Перед нами стояла задача выстроить международную схему издатель-подписчик, в которой ядро обменивается данными с сервисами, о которых невозможно знать наверняка, работают ли они. И самое главное, нам предстояло обеспечить надежную бесперебойную работу при большом количестве трафика. Мы осознавали, что трафика будет много, причем идти он будет не только из ядра в регионы, но и наоборот. Нам нужен был такой механизм очередей, чтобы задерживать передачу данных, когда принимающие серверы слишком загружены, и при этом избежать сценария, в котором источник данных бы заклинивало на бесконечных повторных попытках отправить запрос. Мы не могли допустить потерю даже мельчайшего фрагмента данных и должны были синхронизировать всю передаваемую информацию. Так нам пришло в голову использовать очереди сообщений. Почему? Они позволяют добавлять промежуточные слои программного обеспечения, на которых хранятся все передаваемые данные. В зависимости от настройки очередей можно увеличивать надежность системы, запрашивая подтверждение приема пакета данных и используя цепочку доверия.
Итак, мы наконец поняли, что делать, но ещё не придумали, как. У каждого из нас были идеи одна гениальнее другой! Начали, конечно, с самого простого варианта «сохраним где-нибудь неподтвержденные данные, и будем продолжать пробовать их передать, пока не сработает». Мы даже пытались настраивать очереди сообщений через Redis (работает хорошо, но ненадежно). А потом наткнулись на платформу RabbitMQ и протокол AMQP. Надо признать, до этого большинство членов команды про этот протокол вообще не знали. Опыта работы с очередями сообщений у нас не было, так что пришлось многому учиться с нуля. Помучившись на этапе проб и ошибок, мы наконец приручили эту технологию, а что было дальше, вы знаете. Для внутренних сообщений, которые должны выполняться асинхронно, мы используем RabbitMQ. В каждом регионе у нас по AMQP-брокеру плюс один в ядре. Для передачи сообщений между ядром и регионами мы используем плагин Shovel.
AMQP и HTTP: за и против
Мы уже год пользуемся технологией цепочек сообщений, накопили достаточный опыт, достигли отличных результатов. Брокеры RabbitMQ — основа передачи данных между компонентами нашего продукта. И все равно мы чуть ли не каждый день спорим, что лучше, AMQP или HTTP. Народ иногда даже ругается на этой почве, и приходится начинать длинные бессмысленные дискуссии о том, хорошая или плохая штука эти ваши RabbitMQ и AMQP. Обычно звучат четыре мнения (ну, по крайней мере я столько насчитал) по этому вопросы (что использовать для внутренней асинхронной передачи данных между компонентами):
- Мне нравится HTTP.
- А мне нравится AMQP.
- Мне без разницы, пользуюсь тем, что выбрали до меня.
- Не важно, какой протокол использовать, лишь бы данные были синхронизированы.
Чтобы не отклоняться от темы статьи, точки зрения из пунктов 3 и 4 предлагаю обсудить в комментариях. А тут давайте сфокусируемся на первых двух мнениях.
Предложить-то я предложил, но на самом деле для меня начинается самая сложная часть статьи. Дело в том, что «нравится» — не самое подходящее слово. Имеют ли разработчики вообще право на вкусы в технических вопросах? Или нам все-таки следует анализировать факты и выбирать то, что лучше всего подходит в каждом конкретном случае? Все-таки в нашей работе главное не инстинкты, а факты (хотя чутьё тоже важно!). Поэтому переходим к чистым фактам:
- Оба протокола разрешают передачу данных между компонентами
- Оба протокола прозрачны (всегда есть возможность отследить запросы и возвращаемые ответы)
- Оба протокола хорошо документирваны
- AMQP работает в асинхронном режиме
- HTTP — синхронный протокол
- В HTTP легко устранять баги
- Разработчики хорошо знают HTTP
- HTTP хорошо отображается в интерфейсе
- AMQP легко поддерживать и масштабировать
- AMQP гарантирует доставку сообщений
- Если вы используете HTTP, вам потребуется какой-нибудь механизм обнаружения сервисов
- Протоколу AMQP нужно знать, где расположен брокер, чтобы получить доступ к очереди для чтения или записи сообщений
- RabbitMQ использует механизмы разветвления и встроенные плагины shovel и federation для перемещения сообщений между брокерами
- Если RabbitMQ перезагружается во время незавершенной обработки сообщения, оно будет автоматически перенаправлено в очередь, где его обработает другая серверная служба
- HTTP поддерживается практически на всех языках программирования
- RabbitMQ (а, значит, и AMQP) поддерживается на нескольких языках программирования (JAVA, .NET, Ruby, Python, PHP, Objective-C, Scala, Groovy и Grails, Clojure, Jruby, Javascript, C, C ++, GO, Erlang, Haskell, OCaml, Unity 3D, Perl, Common Lisp, COBOL)
- …
Если продолжить, список фактов растянется как минимум на несколько страниц. Однако, думаю, ключевой информации я предоставил достаточно, чтобы вы могли выбрать тот или иной протокол в зависимости от ситуации.
Плюсы HTTP
- Устранять ошибки в HTTP-запросах очень легко, причем делать это можно многократно. Отладка сообщений AMQP сложнее (понадобится подключение к очереди, библиотеки, возможно, придется разрабатывать скрипт).
- Разработчики знают HTTP: не нужно дополнительно обучать каждого новичка на проекте.
- HTTP — самый поддерживаемый протокол в интернете. Поэтому полезно, чтобы у вашего API была HTTP-версия
Плюсы AMQP
- У AMQP надежная доставка сообщений. Это асинхронный протокол, так что о доставке можно вообще не волноваться.
- Для доставки и получения сообщений достаточно знать хост или IP кластера брокеров AMQP. В протоколе HTTP хосты и IP могут варьироваться в зависимости от региона.
- Доступен метод разветвлений, в рамках которого одно сообщение информирует несколько разных компонентов. То есть сообщений становится меньше.
Что нужно учитывать при работе с AMQP
Чтобы доставлять и получать AMQP-сообщения, нужен брокер. Брокер — это ни что иное, как сервер, который получает, сохраняет и доставляет сообщения. В зависимости от издержек и инфраструктуры проекта брокеры способны усложнить вам жизнь, ведь вам придется настраивать и поддерживать один, несколько или целую федерацию брокеров.
Мы отдали управление серверами на аутсорс в CloudAMQP. С одной стороны теперь не приходится беспокоиться об обслуживании брокеров, но с другой — это дополнительные расходы.
Заключение (почти)
Мое мнение такое: если вы собрались общаться с внешним миром (то есть делаете публичный API), у HTTP есть всё необходимое. Везде поддерживается, все его знают и используют. Кроме того, если обнаружится проблема с передачей данных, это не ваша головная боль. Это клиенту API придется снова выполнять запрос, если что-то пошло не так.
Если вам нужно обеспечить внутренний обмен данными и контролировать каждый запрос, я бы посоветовал AMQP. Простой, надежный, масштабируемый и шустрый протокол, который поддерживают большинство языков.
У меня нет сомнений, что и HTTP, и AMQP — это очень крутые протоколы. Но только один из них по умолчанию, что очень важно, повышает надежность передачи данных, и только один легко масштабируется почти без дополнительных настроек. А поскольку запросы не блокируют работу сервисов, вы можете использовать ресурсы для других процессов.
И еще один аргумент в пользу AMQP. Зачем заново изобретать колесо и создавать собственные процессы для повышения надежности? Зачем добавлять дополнительный код, который потом нужно поддерживать? Просто потому что можем? Мой совет простой: если делаете асинхронные запросы, используйте AMQP с RabbitMQ.
Настоящее заключение
Вы наверное уже поняли, что вся эта дискуссия не имеет смысла. Искать ответ на вопрос, что лучше, HTTP или AMQP, так же нелепо, как сравнивать квадратное с мягким. Мы в Live and Dev не раз попадали в эту ловушку.
Не надо так. Сосредоточьтесь на том, что действительно важно. Почему мы выбираем ту или иную технологию? Какие достоинства и недостатки есть у нашего выбора? И как извлечь из него максимум?
Конечно, обзор выбранной инфраструктуры — вещь полезная, но только если не забывать учитывать, когда и почему мы её используем.
Перевод статьи «AMQP vs. HTTP» by Federico José Sörenson Sánchez