Cloud-Native Application Architectures

oreilly-cover-migrating-to-cloud-native-application-architecturesВесной этого года издательство O`Reilly выпустило небольшую, но очень ладно скроенную книжку Мэтта Стайна (Matt Stine) Migrating to Cloud-Native Application Architectures. Скачать её бесплатно(за регистрацию) можно на сайте Pivotal по этой ссылке: Free O’Reilly Microservices eBook. Посредством очень простых рассуждений автор рассказывает нам, почему организации вынуждены буду заняться приложениями в облачной архитектуре, а заодно и чем такая архитектура отличается от традиционной. Кроме того, мы узнаем про манифест The Twelve-Factor App (русский), зачем нужны микросервисы, инфраструктуры, предоставляемые в режиме самообслуживания, и взаимодействия посредством программных интерфейсов. Для тех, кто не станет читать эту книжку, я постараюсь изложить её содержание в нескольких словах

Предприятия тратят большие средства на управления центрами обработки данных. Бесчисленные человеко-часы посвящены работам по установке, настройке и поддержке серверов, систем хранения и сетей передачи данных. Эти операции очень важны для поддержания инфраструктуры, но не приносят дополнительной ценности для бизнеса. Скорее наоборот, ошибки администраторов при выполнении плановых работ являются основной причиной большинства сбоев в работе организации. Все более-менее понимают, что эти операции надо было бы давно унифицировать, стандартизировать и автоматизировать, но архитектура прикладных систем не позволяет это сделать. Поэтому, основной стратегией предприятий в области управления изменениями остается минимизация их количества. Мы выстраиваем эшелонированную оборону против изменений, включающую множество барьеров: процедуры авторизации изменений, разнообразное тестирование релизов, разработку и согласование нескольких килограмм бумажной документации. Это все отлично работает, пока изменение не случилось. Но рано или поздно наступает момент, когда надо решиться прыгнуть в холодную воду и установить изменение. Однако, после осуществления изменения эта стратегия становится совершенно бессмысленной и даже вредной.  Мы не можем обнаружить и быстро, не дожидаясь ощутимого ущерба, исправить ошибку. Непонятно в какой момент такая ошибка вылезет, и какое изменение следует откатить для её устранения. Так что корректирующее изменение  нам придется делать по длинному циклу.

Стратегия изменений в облачных вычислениях принципиально иная: мы часто ошибаемся, но быстро, не дожидаясь серьезных последствий, исправляем свои ошибки. Эти две стратегии несовместимы. Поэтому аналитики и рассуждают про bi-modal IT или pace-layer approach. Принципиальная несовместимость подходов вызывает разные требования к архитектуре приложений. Требования стратегии номер два следующие.

Первое и основное требование – безопасность (safety). Мы не говорим о превентивной безопасности, почитаемой стратегией номер один. Речь не идет об исчерпывающей документации, утверждении изменений на архитектурных советах и глубоком регрессионном тестировании. Нам нужно немного иное:

  • Наблюдаемость хода исполнения приложения(visibility). Архитектура системы должна предоставлять инструменты, способные обнаружить или даже прогнозировать отказы и сбои. Мы должны постоянно получать оповещения о здоровье приложения и четко понимать, какие значения измерений свидетельствуют о том, что что-то пошло не так.
  • Изоляция сбоев(fault isolation). Для того чтобы снизить риск наступления масштабного сбоя необходимо ограничения размера функциональных компонент. Монолитное приложение обрушается целиком. В такой архитектуре, какой-нибудь несущественный отчет, запускаемый раз в квартал, может стать причиной деградации приложения массового обслуживания. Микросервисная архитектура снижает вероятность таких событий, однако не исключает их полностью.
  • Отказоустойчивость(fault tolerance).  Сильная связность программных компонент может привести к каскадному обрушению системы в целом. Это похоже на веерные отключения электроснабжения, когда из-за локального сбоя страдают большие группы потребителей услуг. Такие ситуации особенно вероятны при работе с общей базой данных и использовании синхронных вызовов удаленных процедур (RPC-style SOA). Например, несколько программ вызывают сервис текущего курса доллара. Сервис недоступен. Не возвращая управления инициировавшей этот запрос системе(т.е. синхронно), программы пытаются вызвать сервис повторно. Как только сервис восстановился, его тут же сметает волна неотработанных ранее запросов и он снова ложится. Приложения верхнего уровня недоступны, т.к. заблокированы ожиданием ответа из-за синхронного вызова веб-сервиса. Следующую волну нагрузки создадут раздосадованные пользователи, нажимающие кнопку Ctrl-F5 в своих браузерах. Где-то в глубине этой архитектуре должны бы были быть API Gateway или хотя бы сервисная шина ESB. Но смысл этих безделушек никогда не был понятен разработчикам информационных систем, и потому: не было гвоздя, подкова пропала…
  • Автоматическое восстановление(automated recovery). Обнаружение и локализация отказов совершенно бесполезны, если вы не знаете что с этим делать. Традиционный подход заключается в том, что выдать сообщение об ошибке и как ни в чем не бывало продолжить работу. Зачастую программисты делают такие сообщения для себя. И их смысловая нагрузка ограничивается сообщением, что что-то пошло не так и надо чуть-чуть доработать код. Если же сообщение не вылезло в ходе отладки, то код вместе с ним отправится в тестирование, а затем в продуктив. Когда, наконец, такое сообщение вылезет, искать программиста будет несколько затруднительно. Вряд ли он указал в сообщении об ошибке номер своего пейджера. В общем, уведомление о проблеме придет людям, осуществляющим эксплуатацию. И это не очень правильно. Получателем таких сообщений должна быть система, управляющая выполнением программного комплекса. Для каждого такого сообщения должна быть запрограммирована последовательность действий по восстановлению. В самом простом случае реакция заключается в том, чтоб перезапустить неработающий модуль. Расскажите программисту о том, что его приложение будут постоянно убивать и поднимать заново. При этом оно должно корректно работать и более-менее быстро восстанавливаться (Альтернативный вариант – программист постоянно носит с собой пейджер и при получении сообщения в течении пары минут создает, тестирует и развертывает очередной билд). В идеале, несколько таких приложений должно быть запущено одновременно. Но это уже скорее о втором свойстве – масштабирование (scale)

 

С масштабированием все, вроде бы, просто. На протяжении десятилетий мы делали примерно так. Приходили к заказчику и спрашивали: какова будет пиковая нагрузка? Приписав, на всякий случай, к озвученной цифре один или два нуля справа мы рассчитывали требования к оборудованию. Закупив оборудование и разработав приложения, мы подвергали его нагрузочному тестированию на указанных заказчиком пиковых значениях. Все это  благополучно развертывалось в продуктиве и работало много лет с нагрузкой не более 1-10% от заявленной. Случающиеся иногда превышения пиковой нагрузки имели важный воспитательный эффект для заказчика и финансовых директоров. Первых журили за то, что они предоставили неверные цифры, а вторых мотивировали быстрее подписывать астрономические счета на компьютерное оборудование: «Ваш предшественник зарубил нам закупку экзадаты и видите что случилось 🙁 » Наверное, все мы являлись тайными адептами темной стороны больших данных, но облачные вычисления вывели нас на чистую воду. Злые вендоры рассказали нашим финансовым директорам, что теперь не обязательно покупать все сразу, а масштабироваться можно по мере роста нагрузки. Они даже пообещали сглаживать пиковые нагрузки переносом приложений из нашего частного облако в своё публичное. Вряд ли при разработке приложений кто-либо рассчитывал на такое коварство с их стороны.

Теперь о двенадцати факторах. Все они переведены на русский язык http://12factor.net/ru/, а некоторые даже снабжены картинками. Звучит это, после исправления орфографических ошибок, примерно так:

Двенадцать факторов

I.Кодовая база. Одна кодовая база, отслеживаемая в системе контроля версий, – множество развертываний

II.Зависимости. Явно объявляйте и изолируйте зависимости

III. Конфигурация. Сохраняйте конфигурацию в среде выполнения

IV.Сторонние службы (Backing Services). Считайте сторонние службы (backing services) подключаемыми ресурсами

V.Сборка, релиз, выполнение. Строго разделяйте стадии сборки и выполнения

VI.Процессы. Запускайте приложение как один или несколько процессов, не сохраняющих внутреннее состояние (stateless)

VII. Привязка портов (Port binding). Экспортируйте сервисы через привязку портов

VIII. Параллелизм. Масштабируйте приложение с помощью процессов

IX.Утилизируемость (Disposability). Максимизируйте надежность с помощью быстрого запуска и корректного завершение работы

X.Паритет разработки/работы приложения. Держите окружения разработки, промежуточного развёртывания (staging) и рабочего развёртывания (production) максимально похожими

XI.Журналирование (Logs). Рассматривайте журнал как поток событий

XII. Задачи администрирования. Выполняйте задачи администрирования /управления с помощью разовых процессов

 

О многих из этих факторов мы ранее уже говорили в этом блоге. Пожалуй, только о факторе IV. Сторонние службы (Backing Services) речь шла немного в другом аспекте, с точки зрения паттерна Inversion of Control (см. Почему не все сервисы одинаково полезны). Все это совершенно правильно и все это абсолютно не нужно пока у вас нет частной облачной инфраструктуры и стратегии управления изменениями номер два. Или у кого-то в средних и крупных организациях уже есть?

Cloud-Native Application Architectures: 8 комментариев

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *