Найти тему
UncaughtException

AMQP vs HTTP

Оглавление

Перевод статьи «AMQP vs HTTP» от UncaughtException.

Когда я только начал планировать эту статью, я думал, что опишу различия между протоколами AMQP и HTTP, подробно расскажу про все заголовки и зачем они нужны, и как устроены потоки передаваемых сообщений и пакетов, и прочее, и прочее, и прочее… А потом я понял, что всё это уже написали до меня. Кому надо узнать справочную информацию о протоколах, может просто погуглить. А если вы надеетесь получить эти базовые знания из этой статьи, дайте-ка я нагуглю их за вас: AMQP, HTTP. А вот если вас интересует разбор реальных случаев применения AMQP и HTTP и аргументы за и против каждого протокола, то вы пришли по адресу.

AMQP vs HTTP
AMQP vs 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 не раз попадали в эту ловушку.

Не надо так. Сосредоточьтесь на том, что действительно важно. Почему мы выбираем ту или иную технологию? Какие достоинства и недостатки есть у нашего выбора? И как извлечь из него максимум?

Конечно, обзор выбранной инфраструктуры — вещь полезная, но только если не забывать учитывать, когда и почему мы её используем.