Монолит вместо микросервисов

01 июня 2023
Монолит вместо микросервисов

Идти против тренда непросто, но это иногда приносит хороший результат. Расскажем, почему в одном из сервисов Amazon полностью отказалась от микросервисной архитектуры в пользу монолита. Ещё обсудим обновления полезных библиотек и экспериментальный JIT-компилятор, включённый в первое превью Ruby 3.3.0.

Amazon отказывается от микросервисов?

В то время, как разные компании разбивают монолиты на микросервисы, некоторые делают полностью противоположные вещи. Если против тренда идёт никому не известная компания, то можно покрутить пальцем у виска и не брать это в расчёт. Но когда мы говорим об опыте Amazon, игнорировать его будет странно. Мы обратили внимание на этот кейс после публикации в блоге автора Ruby on Rails, Дэвида Хейнемейера Ханссона. Кстати, мы брали у него интервью, которое можно найти на нашем сайте.

Команда сервиса Amazon Prime Video решила полностью отказаться от микросервисной архитектуры, заменив её монолитом. И результат оказался ошеломляющим — удалось сэкономить почти 90% эксплуатационных расходов, а система стала проще. Звучит удивительно, поскольку их инфраструктура изначально проектировалась как serverless-решение с прицелом на независимое масштабирование каждого компонента. Но в процессе использования был достигнут жёсткий предел масштабирования, а стоимость компонентов была бы непомерно высока.

Сам сервис, который они строили, состоял из трёх основных компонентов: медиаконвертера, анализаторов дефектов и оркестратора потоков для управления всем этим безобразием. Первая ошибка: отдать управление оркестровкой компоненту AWS Step Function. Последнему для эффективной работы требовалось каждую секунду потока выполнять по несколько переходов состояния. Так что вскоре они упёрлись в лимит аккаунта, а также высокую стоимость, так как за каждый такой переход взимается плата.

Вторая проблема была ещё интереснее. Каждый анализатор дефектов был реализован, как микросервис, использующий AWS Lambda для обработки кадров. Эти кадры, в свою очередь, готовились другим микросервисом, который разбивал видео и временно загружал полученные изображения в объектное хранилище AWS S3. Всё это отлично работало, но общее количество вызовов в соответствующий S3 bucket было огромным и стоило слишком дорого.

Всё это, вкупе со сложностью построенной системы, заставило инженеров задуматься, что в их случае микросервисная инфраструктура избыточна и не даёт каких-либо особых преимуществ. Упаковав все упомянутые компоненты в один процесс, они получили высокую скорость, так как обмен данными происходил в памяти. Также это позволило отказаться от объектного S3-хранилища в роли временного буфера. Концептуально вся архитектура осталась прежней, вот только теперь оркестровка выполнялась всего лишь для одного экземпляра, а не множества.

Такие существенные изменения, разумеется, сказались на возможностях масштабирования. Раньше каждый детектор работал отдельно и мог масштабироваться по горизонтали и по вертикали. При горизонтальном масштабировании создавался новый микросервис, который затем подключался к оркестрации. В новой системе такой вариант невозможен и остаётся только вертикальное масштабирование, которое для каждого экземпляра не бесконечно. Для этого случая было придумано решение с клонированием сервиса и выделением лишь нужных типов детекторов.

По словам DHH, во многих отношениях микросервисы — это зомби-архитектура, которая уже стала токсичной. Замена вызовов методов на сетевые вызовы с разделением сервисов в рамках единой согласованной команды почти всегда становится безумной затеей. Вовсе не факт, что микросервисы решат задачу клиента, а вот навредить могут.

Nokogiri 1.15 вышла в релиз

Если вы часто работаете с XML и HTML в Ruby, то наверняка пробовали Nokogiri. Эта библиотека предоставляет простой и понятный API, имея внутри себя нативные парсеры, такие как libxml2, libgumbo и xerces. Она спроектирована быть безопасной по-умолчанию, а также создаёт удобную для разработки абстракцию, которая не пытается исправить поведенческие различия между парсерами. Удобства ради поставляется в виде предварительно скомпилированных гемов для различных платформ. Установка чаще всего выполняется одной командой:

gem install nokogiri

Если вы уже пользовались Nokogiri ранее, то вышедшее обновление должно вас приятно удивить. С момента выхода первой версии, парсер libxml2 использовал ruby_xmalloc для управления памятью. Это было хорошим решением на тот момент, поскольку давало гибкость. Платой за это была производительность. С версии 1.15 у разработчика появляется возможность выбирать. Теперь можно пожертвовать гибкостью в обмен на производительность, выбрав системный malloc вместо ruby_xmalloc. Делается это через переменную окружения:

# "default" here means "libxml2's default" which is system malloc
NOKOGIRI_LIBXML_MEMORY_MANAGEMENT=default

Бенчмарки показывают, что такой финт ушами радикально улучшает производительность. Но при этом возникает риск появления других проблем, таких как раздутый размер кучи и создания условий для вызова OOM-киллера. Насколько такая рокировка может быть оправдана — сказать сложно. Вероятно, для некоторых приложений это будет отличным способом оптимизации.

Помимо этого нововведения была исправлены ошибки в поведении libxml2 и libxslt, вызывающие segfault. Если в документе присутствуют пустые текстовые узлы с созданными для них объектами Ruby, то будет создаваться защитная копия документа. Небольшая потеря скорости, в данном случае, лучше небезопасного доступа к памяти и потенциальному segfault.

Будущий RJIT

12 мая был открыт доступ к первой превью-версии будущего релиза Ruby. Помимо штатного и официально рекомендуемого компилятора YJIT, в сборку добавлен экспериментальный компилятор RJIT. Существующие компиляторы MJIT и YJIT имеют общий недостаток — они оба полагаются на внешние компиляторы. MJIT зависит от компилятора языка C во время выполнения, а YJIT от компилятора Rust во время сборки. Ноу-хау RJIT в том, что он создан на чистом Ruby, что делает его полностью самодостаточным.

Звучит отлично, но пока что RJIT не самый оптимальный вариант, даже с учётом того, что он генерирует код, аналогичный YJIT. Последний значительно быстрее и стабильнее, особенно после оптимизации в будущей версии 3.3.0. 

По словам Такаши Кокубуна (Takashi Kokubun), штатного Ruby-разработчика в Shopify, есть два ключевых фактора, которые для RJIT пока недостижимы. Первый — время прогрева. Для JIT-компиляторов характерно следующее поведение: первое выполнение какой-либо функции будет медленнее, чем последующие вызовы этой же функции. Соответственно, программа со временем начинает работать значительно быстрее. Чем меньше время прогрева, тем лучше.

Второй фактор — объём потребляемой памяти. Если Ruby-приложение развёртывается на небольшой инфраструктуре, то этот фактор не играет большой роли. Но когда речь идёт о крупномасштабных кластерах, то каждый лишний мегабайт начинает существенно влиять на стоимость эксплуатации. Достигнуть компромисса для RJIT будет сложнейшей задачей, так что не стоит пока списывать со счетов YJIT. Но сам факт того, что альтернативные варианты включаются в язык, заставляют задуматься, что в этом направлении есть потенциал для совершенствования.

Ну и напоследок, раз уже начали говорить о грядущем обновлении Ruby, отметим, что нас ждут изменения некоторых гемов в стандартной библиотеке. В частности, будут затронуты RubyGems, bigdecimal, bundler и syntax_suggest.

Экосистема TTY

Пару дней назад обновился парсер tty-option из TTY Toolkit, это побудило нас написать об этом старом, но надёжном наборе инструментов. В нём 24 плагина для взаимодействия с командной строкой. Каждый из них максимально прост и годится для выполнения конкретной задачи. Но при необходимости их легко комбинировать между собой и получать достойный результат. Всё это очень напоминает бар, где каждый напиток хорош сам по себе, но смешайте их и получится что-то новое.

Чтобы получить доступ сразу ко всем инструментам из набора введите следующую команду в терминале:

gem install ‘tty’

Теперь вам станут доступны многие джедайские техники. Например, tty:cursor позволяет перемещать курсор терминала в нужные вам координаты. Также есть простые методы, вроде перемещения курсора на строку вверх или вниз. Ещё есть прекрасная функция очистки экрана целиком, текущей строки или заданного количества строк.

Отдельно отметим tty:screen, возвращающий значения высоты и ширины текущего экрана. Это сразу же позволяет использовать их для форматирования вывода, например:

require 'tty-cursor'
require 'tty-screen'

@cursor = TTY::Cursor
@size = TTY::Screen.size # => [height, width]
@height = @size[0]
@width = @size[1]

def move_cursor_to_required_coordinates(text)
  x = (@size[1] - text.length) / 2
  y = (@size[0]) / 2
  print @cursor.move_to(x, y)
end

def centered_text(text)
  move_cursor_to_required_coordinates(text)
  puts text
end

centered_text("welcome to the center")

Потребуется приличное количество времени, чтобы изучить каждый из 24 гемов, но это того стоит. Рекомендуем попробовать.

 

 

Митапы

Онлайн

Ruby meetup

05 июля 2023

Летом мы встретимся с вами на замечательном Ruby Meetup, который пройдёт в Москве. Программа мероприятия формируется и скоро станет доступна на странице мероприятия. Кстати, если вы не успели подать доклад, то можете это сделать прямо в режиме онлайн. Заявки на участие принимаются до 20 июня.

Теперь следить за митапами Evrone стало удобнее. В Telegram-канале Evrone meetups мы выкладываем анонсы с подробными описаниями докладов, а также студийные записи после мероприятий. А ещё, у нас можно выступить, мы поможем оформить вашу экспертизу в яркое выступление. Подписывайтесь и пишите @andrew_aquariuss, чтобы узнать подробности.

Регистрация

Вакансии

Удаленка / Офис

Evrone 

Мы открыты для новых Ruby-разработчиков. В Evrone можно работать удалённо с первого дня, мы поддерживаем и оплачиваем участие в Open-source проектах и выступления на конференциях, а расти в грейдах можно с помощью честной системы проверки навыков и менторства.

Подробнее

Подписаться
на Digest →
Важные новости и мероприятия без спама
Технологии которыми вы владеете и которые вам интересны
Ваш адрес электронной почты в безопасности - вот наша политика конфиденциальности.