Как выбрать инфраструктурный инструмент
Когда IT-продукт развивается, обязательно наступает момент, когда становится нужно принести в него какой-то новый инструмент или заменить старый на что-то более подходящее. И вроде бы статей на тему выбора инструментов написано много, сказать нового больше нечего, а вопрос все равно остается актуальным, местами даже острым.
Вообще есть несколько популярных подходов:
- Налево пойдешь - хайповый инструмент найдешь
- Направо пойдешь - что-то проверенное и надежное возьмешь
- Прямо пойдешь - любимый инструмент прикрутишь
Они хороши тем, что при их использовании не надо думать. Просто берешь то, что хочется - и дело с концом 😃 Ну а если есть нужда или желание подойти к вопросу более серьезно - прошу под кат, будем разбираться.
Итак, если не “по-быстрому”, то как же выбирать?
1. Составить список требований
Самый первый и самый очевидный шаг. Но не все так просто, как хотелось бы. Он должен быть актуален на прямо сейчас и обозримое будущее. То есть, нужно выдержать баланс между двумя направлениями:
- Не заглядывать в далекое будущее с потенциальным ростом компании “ва многа разов” и увеличением RPS с текущих 0.1 до 1000.
- Не оставить за бортом реальных требований, если и не текущих, то из обозримого будущего (скажем, в 1-3 года)
2. Выбрать несколько кандидатов, отвечающих всем требованиям
А как выберете - провести их сравнительный анализ, учитывая составленные ранее требования. И не забыть учесть еще несколько пунктов:
- Удобство использования.
Инструмент, которым вы собираетесь регулярно пользоваться, не должен чинить препятствий своему использованию, а еще лучше - делать этот процесс приятным и удобным. - Частота обновлений.
Некоторые старые, надежные инструменты со временем уходят в стагнацию и перестают обновляться. В этом случае даже если сейчас такой инструмент представляется идеальным решением, есть довольно большая вероятность, что его вскоре снова придется менять, так как он либо перестанет соответствовать требованиям безопасности, либо не станет реализовывать новые возможности, которые появятся у него быстро развивающихся конкурентов. С другой стороны - молодые проекты. Они могут загнуться из-за маленького комьюнити и недостатка мейнтейнеров. - Наличие комьюнити, интеграций, плагинов.
Отсутствие у нового крутого инструмента большого комьюнити и большого количества интеграций, которые есть у более проверенных его собратьев, может стать очень серьезным препятствием в развитии вашей компании. Отсутствие возможности быстро встроить инструмент в ваши текущие процессы - это ощутимая проблема. С более старыми инструментами, медленнее работающим, менее удобными, вы нередко можете сэкономить десятки, а то и сотни часов работы просто потому, что ваши проблемы уже кем-то решены. А каким бы классным инструмент ни был, на заре своего развития у него всегда есть одно препятствие: пользователям необходимо решать свои проблемы самостоятельно. - Наличие экспертизы в команде.
Даже если незнакомый инструмент не выглядит сложным, а гайды по установке и настройке умещаются на один экран, это отнюдь не значит, что у вас не возникнет сложностей через месяц. А поскольку экспертизы в работе с этим инструментом у вас нет - неизвестно, сколько времени уйдет на устранение ошибок или оптимизацию его работы.
В общем случае при анализе стоит учитывать только основной, общий для всех систем функционал. Я говорю о том, что все без исключения инструменты инфраструктуры рано или поздно устаревают. Сразу думайте о том, как вы будете менять этот инструмент на какой-то другой. Не на какой-то конкретный, а на абстрактный, систему кэширования - на другую систему кэширования. В случае с системами, для которых нет стандартов вроде PSR, для этого придется самостоятельно провести более глубокий анализ, чтобы выявить этот самый общий функционал.
Если речь идет о системе кэширования, то тут можно руководствоваться актуальным PSR. Сама система кэширования при этом может давать значительно больше возможностей как, например, это делает Redis. Я не рекомендую использовать эти возможности в коде напрямую. Конечно, Redis можно использовать не только как систему кэширования, но и как базу данных. Это нормально. А вот использовать его как систему кэширования, в которой используются функции базы данных, не предусмотренные PSR - рано или поздно приведет к проблемам.
3. Взвесить все за и против выбранных инструментов
Даже в схожих ситуациях в схожих компаниях выбор может радикально отличаться, так как ценность того или иного пункта тоже будет меняться. Для кого-то важнее удобство использования системой, для кого-то - размер комьюнити и сопутствующих инструментов, а у кого-то этот инструмент будет встраиваться в настолько быстрорастущий бизнес, что для него основным фактором станет пропускная способность, а вовсе не удобство использования и скорость его внедрения. Вы можете составить таблицу, определив вес для каждой особенности инструментов. Так вы сделаете процесс анализа более наглядным.
Пример из жизни
А теперь давайте пройдемся по какому-нибудь реальному инструменту, который мы попробуем выбрать по схеме выше. В компании, где я работаю, недавно столкнулись с необходимостью сменить сервер очередей. До замены использовался Redis, но он перестал нас устраивать. Объем информации, пропускаемой через него, растет, ценность ее высокая, и мы не готовы терять ее в случае сбоя. Отсюда вытекает главный критерий, по которому он нас не устраивает: надежность доставки сообщений. Маршрутизацией сообщений между очередями, сложной логикой их доставки и прочими подобными вещами мы не занимаемся. Рост же трафика, пропускаемого через очереди, увеличивается максимум в два раза за год. Еще один критерий: скорость запуска нового инструмента в продакшен, нам необходимо запустить его в течение месяца. Поэтому какой-нибудь совсем новый инструмент не подходит, т.к. мы не готовы тратить лишнее время на его внедрение.
На этапе выбора инструмента все свелось к классическому противостоянию:
- RabbitMQ. С ним у пары наших разработчиков уже был опыт работы. Также-это довольно популярный сервер очередей, имеющий богатый набор функционала и работающий по стандарту amqp. Он наиболее хорошо документирован и проще в установке и обслуживании, чем другие брокеры, реализующие amqp.
- Apache Kafka - весьма популярен среди компаний энтерпрайз-уровня. Работает по собственному стандарту.
- NATS долго рассматривался как один из вариантов, т.к. не сразу выяснилось, что он не персистит сообщения, а значит - теряет их после выключения. А еще против него говорило то, что он принимает сообщения только по UDP, что добавляет рисков к их потере.
Disclaimer
Подробный анализ Kafka и RabbitMQ выходит за пределы темы этой статьи, материалов подобного характера предостаточно в интернете. Я же остановлюсь исключительно на выборе согласно нашим собственным критериям.
Итак, оценим двух оставшихся конкурентов по их возможностям и недостаткам.
RabbitMQ
- С ним уже работали некоторые люди в нашей команде, так что у него есть преимущество на старте.
- Есть возможность гибкого роутинга сообщений благодаря протоколу amqp. Фишка крутая, но не учитывается в рейтинге, т.к. это нельзя переиспользовать при переходе на другой брокер. Их использование приведет к усложнению перехода к другому инструменту, когда наступит соответствующий момент.
- Способ кластеризации. У RabbitMQ для кластеризации и поддержки высокой доступности используется синхронизация баз данных. Это работает быстро, четко, но не прощает сетевых ошибок. Другими словами, если ноды брокера находятся на разных серверах, в разных дата-центрах, неизбежно будут возникать сетевые проблемы, которые будут приводить к рассинхронизации данных в нодах.
Shovel
Также есть альтернатива в виде плагина Shovel, который под капотом использует стандарт amqp и просто пересылает сообщения из очереди одного сервера на обменник (exchange) другого, при этом корректно обрабатывая сетевые ошибки, но добавляя ощутимые накладные расходы, т.к. это не копирование сырых данных, а полноценная обработка сообщения.
- Гарантии доставки сообщений зависят от настроек и поддерживаются только два типа:
- at least once, сообщение будет доставлено не менее одного раза (иногда может быть и больше)
- at most once, сообщение будет доставлено не более одного раза (но может и не быть доставлено вовсе)
- Есть возможность включения записи сообщений на диск для того, чтобы они не терялись при перезапуске брокера очередей.
- Пропускная способность у Кролика неплохая, но серьезно падает при включении записи сообщений на диск, до нескольких тысяч сообщений в секунду. У других брокеров пропускная способность на порядки выше (от сотен тысяч до миллионов в секунду), но мы и в эти числа в обозримом будущем укладываемся.
Apache Kafka
- Мы много о нем слышали, но вживую - не видели.
- Реализует только паб/саб, не умеет в маршрутизацию сообщений. Что, опять-таки, не минус, а констатация факта.
- Возможность кластеризации - есть из коробки, без ощутимой потери производительности и ограничений на локальную сеть, что позволяет делать readonly реплики, хранить разные шарды очереди на разных серверах и пр. Минус: требуется еще один инструмент, ZooKeeper.
- Гарантии доставки сообщений также зависят от настроек, но поддерживаются все три возможных типа, включая “exactly once”, т.е. гарантию того, что сообщение будет доставлено получателю ровно один раз, не больше и не меньше. Однако, с этим режимом гарантий доставки возникают сложности при настройке кластеров Кафки. Конечно, соответствующие рецепты уже есть в интернете.
- Запись сообщений на диск не выключается ввиду архитектурных особенностей: очереди в Кафке - это журналы, в которые сообщения добавляются продюсерами, и откуда они читаются консьюмерами. Другими словами, все пришедшие в Кафку сообщения всегда доступны для чтения, в т.ч.давно обработанные.
- Пропускная способность - около 1 миллиона сообщений в секунду.
При сравнении плюсов и минусов этих двух инструментов становится очевидно, что Кафка ощутимо выигрывает. И все же, мы сделали выбор в пользу RabbitMQ. Все дело в самом первом его плюсе: эта система нам уже знакома, и меньше вероятность того, что мы встретимся с проблемами в продакшене. При этом мы не планируем делать географически распределенную систему, т.е. особенности кластеризации Кролика в нашем случае не являются минусом.
У Кафки же его архитектурное отличие приносит значительные сложности. Во-первых, у Кафки нет собственно очереди: у него есть журналы, разбитые на партиции, и из каждой партиции может читать ровно один консьюмер. Мы с такой схемой никогда не работали, и высока вероятность выстрела в ногу при работе с реальными данными в продакшене. Особенно сильно мы чувствуем опаску при мыслях о масштабировании при обработке сообщений. Кролику можно просто добавить консьюмеров. А с Кафкой необходимо заранее продумывать количество партиций и распределение сообщений по ним для сохранения очередности выполнения задач в некоторых случаях.
Наша компания растет и развивается, и мы не зарекаемся от вероятности того, что мы же и будем через пару лет менять RabbitMQ на Kafka, если вдруг наши требования к брокеру очередей изменятся. А чтобы эта замена прошла безболезненно - не станем завязываться на особенности работы текущего инструмента.
Выводы
Если следовать приведенному выше плану, то можно выбрать любой инструмент из доступных вариантов. Конечно, он оставляет место для риска: если выбрать однозначно самый лучший из доступных, но незнакомый инструмент, можно во время эксплуатации наткнуться на подводные камни. Эти риски тоже стоит закладывать при выборе инструмента. Приведу план подготовки к выбору инфраструктурного инструмента еще раз:
- Составить список требований, не упуская реальных и не выдумывая чего-то сверх необходимого.
- Выбрать несколько кандидатов и провести их сравнительный анализ.
- Оценить выигрышные и проигрышные позиции у разных инструментов, руководствуясь текущими приоритетами.
Расскажите, следовали ли вы подобному плану в своей практике? Какие курьезы случались из-за неучтенных требований или особенностей инструмента? Жду вас в телеграм-чате, буду рад услышать ваши истории и пообщаться!