Русский
Русский
English
Статистика
Реклама

Монолит

Google продвигает новый стандарт WebBundles потенциально опасную для веба технологию упаковки веб-сайтов

07.09.2020 12:20:38 | Автор: admin
В общем потоке новостей остался незамеченным совместный призыв продукт-менеджера Chrome Кенджи Бахе и веб-консультанта Google Юсуке Уцуномии об использовании нового стандарта Web Bundles, разработанного Google. На chromium.googlesource появился соответствующий мануал по использованию WebBundles и, собственно, особо о нем больше не говорилось. Запись от лица Базе и Уцуномии была опубликована еще в ноябре 2019 года, но вызвала реакцию сообщества только сейчас, и то, исключительно на нескольких профильных площадках и в одном блоге, посвященном кибербезопасности.



Чем так опасна технология упаковки содержимого веб-страницы в один источник, что это вообще такое, и почему команда веб-разработки Google ступает на очень скользкую дорожку, давайте разбираться ниже.

Web Bundle дело RarJPEG живет


Конкретно о WebBundle писали на Хабре в уже достаточно далеком 2015 году. Тогда автор ComodoHacker выпустил статью "Web Bundle дело RarJPEG живет" с обзором свежего релиза нового инструмента на GitHub.

Принцип WebBudle образца 2015 года прост и дублирует принципы упаковки .exe-файлов: произвольные файлы упаковываются в один файл-контейнер, а на клиентской стороне доступ к ним организуется по имени файла с помощью API.

Релиз 2015 года фактически, был переосмыслением знакомым с имиджбордами пользователям, принципа rarJPEG когда в изображение упаковывалось дополнительное содержимое. Это позволяло обходить ограничения борд на загрузку только изображений и передавать произвольные файлы между пользователями с помощью анонимной платформы.

WebBundle все так же был направлен на обход ограничений по типу файлов: с его помощью в условный PNG можно было запаковать что угодно, вплоть до бинарников, и передать под видом картинки одним архивом.

В 2015 году ComodoHacker очень правильно оценил перспективы WebBundle: технология специфичная и она будет жить, только если ей найдется применение. Сейчас, из 2020 года мы можем смело ответить, что нет, применения технологии не нашлось и в свет она не пошла.

Вот только проблема в том, что в рядах инженеров и веб-разработчиков Google определенно есть завсегдадаи Форчана, и они переосмыслили концепцию WebBundle, выпустив в свет версию 2.0 или, как они сами ее назвали, WebBundles.

Чем WebBundles 2019 года от Google отличается от WebBundle 2015 года


Первое и очевидное за работу взялись ребята из Google. Второе вроде бесполезную сову упаковки в PNG рандомных файлов они сумели натянуть на огромный глобус веб-разработки и сайтостроения.

Если давать TL;DR, то разница между WebBundles и WebBundle выглядит примерно вот так:



Инженеры Google прямо предлагают использовать WebBundles для инкапсуляции нескольких источников в один файл для последующего его отображения в качестве итоговой веб-страницы для пользователя. Фактически, наиболее близкая из существующих сейчас технологий это PDF. Думаю, многие из нас сталкивались хоть раз в своей жизни с необходимостью извлечь из PDF-файла часть его содержимого и в дальнейших комментариях это не нуждается.

Но если Google станет продвигать WebBundles как повсеместный инструмент, для веба могут настать крайне мрачные времена, и вот почему.

Чем опасен WebBundles для современного веба


Современный веб построен на принципе, что для каждого источника есть своя ссылка, то есть мы можем провести декомпиляцию страницы и посмотреть ее содержимое, зачастую, буквально через открытие консоли в браузере.

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

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

Исследователь в области информационной безопасности из компании компании Brave Питер Снайдер так отозвался в своем блоге о созданной Google технологии:

Эта технология может превратить современный интернет из набора ресурсов с гиперссылками (которые можно проверять, выборочно получать или даже заменять) на непрозрачные пузыри, которые работают по принципу все или ничего (например, как уже работают PDF или SWF).

Проблема WebBundles в том, что сам принцип непрозрачной упаковки содержимого веб-страницы в единый монолит делает невозможным проверки, плюс обесценивает уже выстроенный механизм значимости и индексации URL-адресов.

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

Зачем это токсичный чемодан без ручки нужен Google


Сейчас будет озвучен всем известный факт: Google ненавидит блокировщики рекламы. Возможно, они стараются делать вид, что блокировщики это явление, с которым надо жить и которое никуда не денется. Возможно, они сами поддерживают этот мейнстрим. Например, в ноябре в Chrome добавили встроенный блокировщик.

Но давайте будем честны: вся империя Google держится на баннерах и первых трех ссылках поисковой выдачи с пометкой реклама. Это многомиллиардный доход корпорации и вокруг баннеров и этих трех ссылок крутится весь бизнес и империя разработки Google.

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

При этом Google настроена достаточно серьезно. Текущая реализация WebBundles уже интегрирована в стабильные версии Chrome, но пока по умолчанию отключена. Но при желании по chrome://flags вы можете открыть этот ящик Пандоры.


Версия Chrome 85.0.4183.83 (Официальная сборка), (64 бит)

Сейчас WebBundles больше похоже на ружье, которое висит на стене и никогда не выстрелит. Но если Google сильно прижмет и доходы компании значительно просядут из-за падения рекламных бюджетов, в ход может пойти и это оружие. Что пообещает корпорация веб-разработчикам неизвестно, но уже точно понятно, что WebBundles выглядит очень аппетитно для недобросовестных веб-мастеров, которые готовы монетизировать свое хозяйство любыми путями и способами.

Как с этим бороться тоже непонятно, особенно с учетом того, что во главе возможного внедрения web-PDF будет стоять компания, которая занимается разработкой самого популярного браузерного движка на планете. Еще хуже то, что этому движку сейчас нет внятных альтернатив, потому что даже Microsoft уже как два года пристрелили и закопали свою стюардессу EdgeHTML, перейдя на Chromium.

Аналогия с PDF проведена не просто так: базовый принцип отображения и упаковки данных между форматом защиты документов и WebBundles крайне схож. Еще хуже то, что к 2020 году в широком доступе нет инструментов и сервисов (даже платных), которые бы со 100% точностью декомпилировали содержимое PDF и отдавали его пользователю в нужном формате, а мы говорим просто о защите текстовых данных. Какие способы защиты содержимое контейнеров WebBundles могут создать в Google остается только гадать.

Google пока аккуратно позиционирует WebBundles как инструмент для сохранения и передачи веб-сайтов в локальном виде, то есть через носители или Bluetooth. При этом компания называет WebBundles новым стандартом, который может коренным образом изменить интернет, то есть планы по широкому внедрению WebBundles уже есть.



На правах рекламы


Серверы для размещения сайтов любых масштабов это про наши эпичные! Все серверы из коробки защищены от DDoS-атак, скорость интернет-канала 500 Мегабит, автоматическая установка удобной панели управления VestaCP для размещения сайтов и даже автоматическая установка Windows Server на тарифах с 2 ГБ ОЗУ или выше. Поспешите заказать!

Подробнее..

Есть ли перспективы у монолитных web-приложений?

12.11.2020 08:22:24 | Автор: admin

Что лучше для web-приложений - монолит или микросервисы? Многие ответят на этот вопрос, что, мол, все инструменты хороши, если их использовать по назначению. В таком случае у меня, как у человека, в силу своего возраста, довольно консервативного и неохотно воспринимающего непроверенные временем концепции, возникает другой вопрос - а чем хорош монолит? Где его ниша? Стоит ли переключаться на микросервисы или монолит ещё не изжил себя и на мой век хватит?

В фокусе моих интересов не гигантские web-приложения типа Gmail, Facebook, Twitter, а web-приложения, созданные на базе таких платформ, как Wordpress, Drupal, Joomla, Django, Magento и им подобным. Под катом мои субъективные мысли на этот счёт. Ничего нового - всё те же 33 буквы кириллицы и 26 букв латиницы вперемешку.

Причина появления микросервисов

Для начала хорошо бы определить, в чём причина появления микросервисов? Чем оказался плох монолит?

Здесь мне очень помогла статья "Архитектура микросервисов" (автор оригинала - Herberto Graca, перевод - @AloneCoder. Основные отличительные черты микросервисов:

  • разграничение контекстов: что бы ни подразумевалось под словом "контекст";

  • надпроцессное взаимодействие: части одного приложения взаимодействуют посредством HTTP-запросов, а не в рамках процессов одного сервера;

  • независимая масштабируемость: части приложения, как следствие предыдущего пункта могут размещаться на разных аппаратных ресурсах и масштабироваться отдельно от других частей;

  • гетерогенность используемых инструментов: различные части приложения могут быть написаны на различных языках программирования;

На мой взгляд, основная причина появления микросервисов - потребность в независимом масштабировании частей приложения. Всё остальное - либо необходимые условия (разграничение контекстов и надпроцессное взаимодействие), либо следствия (гетерогенность инструментов, независимые команды разработчиков).

Таким образом, основное ограничение монолита - это то, что он не может быть отмасштабирован частично.

Пределы вертикального масштабирования

Вертикальное масштабирование (наращивание мощности аппаратных ресурсов) вполне доступно для монолита. Где же граница, после которой вертикальное масштабирование становится неэффективным? У меня нет большого опыта работы с высоконагруженными системами, поэтому я основываюсь на стороннем опыте. Так, Александр Бындю в своей статье "Переход от монолитной архитектуры к распределенной" даёт такие количественные характеристики:

  • Работа с большими объемами данных - для нас от 500 ГБ и таблицы от 100-150 млн. записей уже считаются большим объемом. ...

  • Работа с нагрузками - либо от пользователей (примерно от 100 запросов в секунду к вашим серверам заставят вас задуматься об оптимизации запросов и скорости отклика), либо от внутренних сервисов. ...

Исходя из этого, могу предположить, что монолитное web-приложение вполне комфортно будет масштабироваться вертикально:

  • на базах общим размером до 0.5ТБ;

  • с таблицами, в которых количество записей не превышает 100 млн.;

  • при сетевых нагрузках не выше 100 запросов/сек.

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

Получается, что, если web-приложение не выходит за указанные рамки (или, что касается базы данных, удерживается в этих рамках), то есть смысл оставаться в рамках монолитной архитектуры.

Микрофронтенды

С некоторым для себя удивлением осознал, что микросервисы - это про масштабирование backend'а и только про него. Пользовательский интерфейс отрабатывает на фронте, в браузере клиента. И по своей сущности является классическим "монолитом" - взаимодействие компонентов фронта происходит либо в рамках одного процесса, либо на уровне процессов одного аппаратного устройства и ни о каком горизонтальном масштабировании речь не идёт в принципе. Причём такое положение одинаково для любого типа фронта - SPA, PWA или классическая HTML-страничка с фрагментами JS. В статьях типа "Разделение монолитного приложения на микросервисы" вы ничего не найдёте про то, как делить монолит, чтобы компоненты фронта соответствовали "своим" микросервисам.

Т.к. зависимость по данным между фронтом и микросервисами остаётся и должна поддерживаться (новый атрибут у сущности в микросервисе может требовать новое поле на форме в UI), то микросервисный подход с бэка "протекает" на фронт в виде микрофронтендов.

Из 4 основных характеристик микросервисов, описанных выше, в разделе "Причина появления микросервисов", к микрофронтендам можно отнести только две:

  • разграничение контекстов;

  • гетерогенность используемых инструментов (если под "инструментами" подразумевать фреймворки - React, Angular, Vue, ...);

В минусе - надпроцессное взаимодействие и горизонтальное масштабирование.

Что характерно, первая причина (разграничение контекстов) является следствием появления микросервисов на бэке и главной причиной возникновения самого понятия "микрофронтенд".

Из неприятного - приемлемых, общепринятых рецептов создания микрофронтендов пока нет. По крайней мере в статьях про разделение монолитного приложения на микросервисы нет ссылок на рецепты создания микрофронтендов, соответствующих микросервисам.

Из непонятного - зачем к web-компонентам, виджетам, портлетам, добавились ещё и микрофронтенды?

Монолитен ли монолит?

Корректно ли вообще говорить о монолитной архитектуре в контексте web-приложений? Ведь любое web-приложение размещается, как минимум, в двух местах - на сервере и в браузере клиента, а классической вообще считается трёхуровневая архитектура.

Если рассматривать классическое web-приложение с точки зрения надпроцессного взаимодействия, то на каждом уровне своя группа процессов (браузер, backend, базы данных), а контексты вполне себе разграничиваются на уровне отдельных модулей (библиотек, компонентов, плагинов). Такая архитектура позволяет масштабироваться горизонтально в определённых пределах - "балансировщик нагрузки + несколько экземпляров backend'а", "база данных на запись + кэширующие in-memory DB на чтение". Но чего себе точно не может позволить классическое web-приложение, так это независимого масштабирования частей приложения на уровне отдельных модулей/плагинов (контекстов).

Получается, что явным признаком монолитного приложения является его развёртываемость в виде единого целого (либо отдельно по уровням - контент для браузера, серверная логика, структура данных).

Плагины

Как ни крути, но в любом приложении есть зацепление (coupling) по данным между пользовательским интерфейсом на клиентской стороне и хранилищем данных на серверной. Если данные хранятся в базе, то они каким-то образом должны быть показаны пользователю (или получены от него). Путём разбиения функциональности приложения на отдельные области (разграничение контекстов) можно очень сильно снизить зацепление между отдельными фрагментами разрабатываемого приложения (модулями). Вплоть до получения плагинов - модулей, подключаемых к приложению по необходимости.

Но внутри плагина сквозное зацепление по данным между пользовательским интерфейсом, бизнес-логикой и хранилищем всё равно остаётся. Поэтому плагины оформляются в виде отдельных пакетов, в которых совместно находятся элементы кода, соответствующие всем трём уровням приложения (UI, бизнес-логика, данные). Сами пакеты распространяются через соответствующие менеджеры пакетов (maven, composer, npm).

Платформы

Многие современные web-приложения строятся на базе какой-нибудь платформы (framework - Wordpress, Django, ...), предоставляющей базовую функциональность, и набора плагинов для этой платформы (публичных или собственного производства), позволяющего удовлетворять бизнес-потребности заказчика.

И если плагины позволяют разделить функциональность приложения на части, то платформы - это как раз тот инструмент, что вновь объединяет части в единое целое. Причём делают они это отдельно для каждого уровня (UI, бизнес-логика, данные), предлагая плагинам соответствующую инфраструктуру для встраивания в приложение на отдельном уровне и для передачи данных плагина между уровнями:

Зачастую платформы используют метаданные менеджеров пакетов (файлы package.json, composer.json соответствующих пакетов) для распознавания "своих" плагинов в общей массе зависимостей приложения.

Режимы работы web-приложения

Web-приложение в общем случае может работать в следующих режимах:

  • Web UI: поддержка работоспособности пользовательского интерфейса на клиенте (раздача статики, обмен данными, представление данных в браузере);

  • Web API: backend-сервисы для доступа к бизнес-функциям приложения (с фронта или от сторонних приложений);

  • CLI: консольный доступ к бизнес-функциям приложения (как правило, сервисным);

  • Cron: выполнение задач по-расписанию (например, зачистка устаревших или временных данных);

  • Async: асинхронная обработка ресурсоёмких событий (например, списание продуктов со склада при оформлении заказа в магазине);

Для работы в режимах, допустим, CLI и Cron приложению не обязательно нужно находиться на одном аппаратном устройстве. Несмотря на общую кодовую базу, приложение в разных режимах можно запускать на разных серверах (тоже своего рода горизонтальное масштабирование). Главное, что их связывает - единое хранилище данных, которое, кстати, можно попытаться разбить "побазно" и каждую базу разместить на отдельном сервере (подход из мира микросервисов). Для приложения в режиме Web API можно сделать балансировку нагрузки и также разнести экземпляры приложения по разным серверам.

Резюме

Строго говоря, термин "монолит" неприменим к web-приложениям в силу их распределённости (клиент-сервер). Можно принять за "монолитное" приложение, у которого:

  • единая кодовая база (с учётом, что клиентская часть реализована на HTML/CSS/JS, а серверная - на Java/C#/PHP/Python/JS/Go/..., но собирается всё в единое приложение);

  • модули (plugins), реализующие различные контексты приложения, объединяются одной платформой (framework) для обеспечения сквозной работоспособности модулей на различных уровнях приложения (UI / бизнес-логика / данные);

  • общее логическое хранилище данных (которое может быть разнесено на различные сервера по типам данных - файлохранилище, RDBMS, in-memory DBs);

  • приложение в различных режимах работает, как правило, в рамках процессов одного аппаратного устройства (разумеется, с учётом разделения по уровням - UI / бизнес-логика / данные);

На мой субъективный взгляд у приложений такого типа в современном мире есть ещё достаточно перспективное будущее в ограниченной нише мелко-средних web-приложений (БД до 0.5ТБ, < 100 млн. записей на таблицу, < 100 запросов в сек. по сети).

Смысл заморачиваться микросервисами в web-приложении есть только в том случае, если приложению грозит шанс стать популярным и выйти в разряд highload-приложений. Но, как писал классик "Все счастливые семьи похожи друг на друга, каждая несчастливая семья несчастлива по-своему." (с) В случае выхода приложения на highload нужно будет "творчески осмысливать" создавшуюся ситуацию и предпринимать шаги по снижению напряжённости, соответствующие данному конкретному случаю. Благо, что сам характер web-приложения предполагает распределённость и есть некоторое поле не только для вертикального, но и горизонтального масштабирования "монолита".

В обычной, до-highload'овой ситуации достаточно вложить свои интеллектуальные усилия в разделение контекстов в "монолите" (разбиение кодовой базы на плагины) и асинхронное выполнение ресурсоёмких операций, что позволит проще перейти к микросервисам, если горизонтальное масштабирование станет для web-приложения жизненно-важным.

Послесловие

Некоторые на Хабре интересуются, зачем я пишу тут всякое? Отвечаю - подобная писанина помогает упорядочить собственный поток сознания, а иногда и получить из ноосферы полезную обратную связь в виде комментов.

Очень сожалею, если вас напрягло прочтение моего опуса, но прошу отметить, что вы это сделали совершенно добровольно. И если вдруг вы решите поставите посту минус с пометкой "Ничего не понял после прочтения", то попробуйте перечитать ещё раз - вдруг всё-таки что-то поймёте. Или найдите другую причину. Спасибо за понимание :)

Если же кто-то нашёл для себя что-то полезное - я только рад.

"Счастье для всех, даром, и пусть никто не уйдёт " (с) АБС

Подробнее..

История архитектуры Dodo IS ранний монолит

01.10.2020 18:11:51 | Автор: admin

Или каждая несчастная компания с монолитом несчастлива по-своему.

Разработка системы Dodo IS началась сразу же, как и бизнес Додо Пиццы в 2011 году. В основе лежала идея полной и тотальной оцифровки бизнес-процессов, причем своими силами, что еще тогда в 2011 году вызывало много вопросов и скептицизма. Но вот уже 9 лет мы идем по такому пути с собственной разработкой, которая начиналась с монолита.

Эта статья ответ на вопросы Зачем переписывать архитектуру и делать такие масштабные и долгие изменения? к предыдущей статье История архитектуры Dodo IS: путь бэкофиса. Начну с того как начиналась разработка Dodo IS, как выглядела изначальная архитектура, как появлялись новые модули, и из-за каких проблем пришлось проводить масштабные изменения.

Серия статей Что такое Dodo IS? расскажет про:

  1. Ранний монолит в Dodo IS (2011-2015 годы). (You are here)

  2. Путь бэкофиса: раздельные базы и шина.

  3. Путь клиентской части: фасад над базой (2016-2017 годы). (In progress)

  4. История настоящих микросервисов. (2018-2019 годы). (In progress)

  5. Законченный распил монолита и стабилизация архитектуры. (In progress)

Изначальная архитектура

В 2011 году архитектура Dodo IS выглядела так:

Первый модуль в архитектуре прием заказа. Бизнес-процесс был такой:

  • клиент звонит в пиццерию;

  • трубку берет менеджер;

  • принимает по телефону заказ;

  • параллельно набивает его в интерфейсе приема заказа: учитывается информация о клиенте, данные по деталям заказа, адрес доставки.

Интерфейс информационной системы выглядел примерно так

Первая версия от октября 2011:

Чуть улучшенная в январе 2012

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

Их первое решение определило дальнейшую судьбу технологического стека:

  • Backend на ASP.NET MVC, язык C#. Разработчики были дотнетчиками, этот стек был им знаком и приятен.

  • Фронтенд на Bootstrap и JQuery: интерфейсы пользователя на самописных стилях и скриптах.

  • База данных MySQL: без затрат на лицензии, простая в использовании.

  • Серверы на Windows Server, потому что .NET тогда мог быть только под Windows (Mono обсуждать не будем).

Физически это все выражалось в дедике у хостера.

Архитектура приложения приема заказа

Тогда уже все говорили о микросервисах, а SOA лет 5 использовалось в крупных проектах, например, WCF вышел в 2006 году. Но тогда выбрали надежное и проверенное решение.

Вот оно.

Asp.Net MVC это Razor, который выдаёт по запросу с формы или от клиента HTML-страницу с рендерингом на сервере. На клиенте уже CSS и JS-скрипты отображают информацию и, по необходимости, выполняют AJAX-запросы через JQuery.

Запросы на сервере попадают в классы *Controller, где в методе происходит обработка и генерация итоговой HTML-страницы. Контроллеры делают запросы на слой логики, называемый *Services. Каждый из сервисов отвечал какому-то аспекту бизнеса:

  • Например, DepartmentStructureService выдавал информацию по пиццериям, по департаментам. Департамент это группа пиццерий под управлением одного франчайзи.

  • ReceivingOrdersService принимал и рассчитывал состав заказа.

  • А SmsService отправлял смс, вызывая API-сервисы по отправке смс.

Сервисы обрабатывали данные из базы, хранили бизнес-логику. В каждом сервисе был один или несколько *Repository с соответствующим названием. В них уже находились запросы к хранимым процедурам в базе и слой мапперов. В хранимках была бизнес-логика, особенно много в тех, которые выдавали отчетные данные. ОРМ не использовался, все полагались на написанный руками sql.

Еще был слой доменной модели и общих классов-хелперов, например, класс Order, хранивший заказ. Там же, в слое, находился хелпер для преобразования текста отображения по выбранной валюте.

Всё это можно представить такой моделью:

Путь заказа

Рассмотрим упрощенный первоначальный путь создания такого заказа.

Изначально сайт был статический. На нем были цены, а сверху номер телефона и надпись Хочешь пиццу звони по номеру и закажи. Для заказа нам нужно реализовать простой flow:

  • Клиент заходит на статический сайт с ценами, выбирает продукты и звонит по номеру, который указан на сайте.

  • Клиент называет продукты, которые хочет добавить в заказ.

  • Называет свой адрес и имя.

  • Оператор принимает заказ.

  • Заказ отображается в интерфейсе принятых заказов.

Все начинается с отображения меню. Залогиненный пользователь-оператор в один момент времени принимает лишь один заказ. Поэтому draft-корзина может храниться в его сессии (сеанс пользователя хранится в памяти). Там объект Cart, в котором продукты и информация о клиенте.

Клиент называет продукт, оператор нажимает на + рядом с продуктом, и на сервер отправляется запрос. По продукту вытаскивается информация из базы и добавляется информация о продукте в корзину.

Примечание. Да, здесь можно не вытаскивать продукт из базы, а передавать с фронтенда. Но для наглядности я показал именно путь из базы.

Далее вводим адрес и имя клиента.

При нажатии Создать заказ:

  • Запрос отправляем в OrderController.SaveOrder().

  • Получаем Cart из сессии, там лежат продукты в нужном нам количестве.

  • Дополняем Cart информацией о клиенте и передаем в метод AddOrder класса ReceivingOrderService, где он сохраняется в базу.

  • В базе есть таблицы с заказом, составом заказа, клиентом и они все связаны.

  • Интерфейс отображения заказа идет и вытаскивает последние заказы и отражает их.

Новые модули

Прием заказа был важен и необходим. Нельзя сделать бизнес по продаже пиццы, если нет приема заказа для продажи. Поэтому система начала обрастать функционалом примерно с 2012 по 2015 года. За это время появилось много различных блоков системы, которые я буду называть модулями, в противовес понятию сервиса или продукта.

Модуль это набор функций, которые объединены какой-то общей бизнес-целью. При этом физически они находятся в одном приложении.

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

Технически модули оформлялись как Area (вот такая идея даже осталась в asp.net core). Там были отдельные файлы для фронтенда, моделей, а также свои классы контроллеров. В итоге система преобразовалась из такой...

в такую:

Некоторые модули реализованы отдельными сайтами(executable project), по причине совсем уже отдельного функционала и частично из-за несколько отдельной, более сфокусированной разработки. Это:

  • Site первая версия сайта dodopizza.ru.

  • Export: выгрузка отчетов из Dodo IS для 1C.

  • Personal личный кабинет сотрудника. Отдельно разрабатывался и имеет свою точку входа и отдельный дизайн.

  • fs проект для хостинга статики. Позже мы ушли от него, переведя всю статику на CDN Akamai.

Остальные же блоки находились в приложении BackOffice.

Пояснение по названиям:

  • Cashier Касса ресторана.

  • ShiftManager интерфейсы для роли Менеджер смены: оперативная статистика по продажам пиццерии, возможность поставить в стоп-лист продукты, изменить заказ.

  • OfficeManager интерфейсы для роли Управляющий пиццерии и Франчайзи. Здесь собраны функции по настройке пиццерии, её бонусных акций, прием и работа с сотрудниками, отчеты.

  • PublicScreens интерфейсы для телевизоров и планшетов, висящих в пиццериях. На телевизорах отображается меню, рекламная информация, статус заказа при выдаче.

Они использовали общий слой сервисов, общий блок доменных классов Dodo.Core, а также общую базу. Иногда еще могли вести по переходам друг к другу. В том числе к общим сервисам ходили и отдельные сайты, вроде dodopizza.ru или personal.dodopizza.ru.

При появлении новых модулей старались по максимуму переиспользовать уже созданный код сервисов, хранимых процедур и таблиц в базе.

Для лучшего понимания масштаба модулей, сделанных в системе, вот схема из 2012 года с планами развития:

К 2015 году всё на схеме и даже больше было в продакшн.

  • Прием заказа перерос в отдельный блок Контакт Центра, где заказ принимается оператором.

  • Появились общедоступные экраны с меню и информацией, висящие в пиццериях.

  • На кухне есть модуль, который автоматически воспроизводит голосовое сообщение Новая пицца при поступлении нового заказа, а также печатает накладную для курьера. Это сильно упрощает процессы на кухне, позволяет не отвлекаться на большое количество простых операций сотрудникам.

  • Блок доставки стал отдельной Кассой Доставки, где заказ выдавался курьеру, который предварительно встал на смену. Учитывалось его рабочее время для начисления зарплаты.

Параллельно с 2012 по 2015 появилось более 10 разработчиков, открылось 35 пиццерий, развернули систему на Румынию и подготовили к открытию точек в США. Разработчики уже не занимались всеми задачами, а были разделены на команды. каждая специализировалась на своей части системы.

Проблемы

В том числе из-за архитектуры (но не только).

Хаос в базе

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

Но за 4 года разработки в базе оказалось около 600 таблиц, 1500 хранимых процедур, во многих из которых была еще и логика. Увы, хранимые процедуры не приносят особого преимущества при работе с MySQL. Они не кэшируются базой, а хранение в них логики усложняет разработку и отладку. Переиспользование кода тоже затруднено.

На многих таблицах не было подходящих индексов, где-то, наоборот, было очень много индексов, что затрудняло вставку. Надо было модифицировать около 20 таблиц транзакция на создание заказа могла выполняться около 3-5 секунд.

Данные в таблицах не всегда были в наиболее подходящей форме. Где-то нужно было сделать денормализацию. Часть регулярно получаемых данных была в колонке в виде XML-структуры, это увеличивало время выполнения, удлиняло запросоы и усложняло разработку.

К одним и тем же таблицам производились очень разнородные запросы. Особенно страдали популярные таблицы, вроде упоминавшейся таблицы orders или таблицы pizzeria. Они использовались для вывода оперативных интерфейсов на кухне, аналитики. Еще к ним обращался сайт(dodopizza.ru), куда в любой момент времени могло придти внезапно много запросов.

Данные не были агрегированными и много расчетов происходило на лету средствами базы. Это создавало лишние вычисления и дополнительную нагрузку.

Часто код ходил в базу тогда, когда мог этого не делать. Где-то не хватало bulk-операций, где-то надо было бы разнести один запрос на несколько через код, чтобы ускорить и повысить надежность.

Связность и запутанность в коде

Модули, которые должны были отвечать за свой участок бизнеса, не делали этого честно. Некоторые из них имели дублирование по функциям для ролей. Например, локальному маркетологу, который отвечает за маркетинговую активность сети в своем городе, приходилось пользоваться как интерфейсом Админа (для заведения акций), так и интерфейсом Менеджера Офиса (для просмотра влияния акций на бизнес). Конечно, внутри оба модуля использовали один сервис, который работал с с бонусными акциями.

Сервисы (классы в рамках одного монолитного большого проекта) могли вызывать друг друга для обогащения своих данных.

С самими классами-моделей, которые хранят данные, работа в коде велась различно. Где-то были конструкторы, через которые можно было указать обязательные поля. Где-то это делалось через публичные свойства. Конечно, получение и преобразование данных из базы было разнообразным.

Логика была либо в контроллерах, либо в классах сервисов.

Это вроде незначительные проблемы, но они сильно замедляли разработку и снижали качество, что приводило к нестабильности и ошибкам.

Сложность большой разработки

Трудности возникли и в самой разработке. Нужно было делать разные блоки системы, причем параллельно. Вместить нужды каждого компонента в единый код становилось все труднее. Было не просто договориться и угодить всем компонентам одновременно. К этому добавлялись ограничения в технологиях, особенно касаемо базы и фронтэнда. Нужно было отказываться от JQuery в сторону высокоуровневых фреймворков, особенно в части клиентских сервисов (сайт).

В каких-то частях системы могли бы использоваться базы, более подходящие для этого. Например, позднее у нас был прецедент перехода с Redis на CosmosDB для хранения корзины заказа.

Команды и разработчики, занимающиеся своей областью явно хотели большей самостоятельности для своих сервисов, как в части разработки, так и в части выкатки. Конфликты при мерже, проблемы при релизах. Если для 5 разработчиков эта проблема несущественна, то при 10, а уж тем более при планируемом росте, все стало бы серьёзнее. А а впереди должна была быть разработка мобильного приложения (она стартанула в 2017, а в 2018 было большое падение).

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

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

Как блог Сила ума положил кассы в ресторанах

Если рост сети пиццерий (и нагрузки) продолжался бы в том же темпе, то через некоторое время падения были бы уже такими, что система и не поднимется. Хорошо иллюстрирует проблемы, с которыми мы начали сталкиваться к 2015 году вот такая история.

В блоге Сила ума был виджет, который показывал данные по выручке за год всей сети. Виджет обращался к публичному API Dodo, которое предоставляет эти данные. Сейчас эта статистика доступна на http://dodopizzastory.com/. Виджет показывался на каждой странице и делал запросы по таймеру каждые 20 секунд. Запрос уходил в api.dodopizza.ru и запрашивал:

  • количество пиццерий в сети;

  • общую выручку сети с начала года;

  • выручку за сегодня.

Запрос на статистику по выручке шел сразу в базу и начинал запрашивать данные по заказам, агрегировать данные прямо на лету и выдавать сумму.

В эту же таблицу заказов ходили Кассы в ресторанах, выгружали список принятых за сегодня заказов, в неё же добавлялись новые заказы. Кассы делали свои запросы каждые 5 секунд или по обновлению страницы.

Схема выглядела так:

Однажды осенью, Федор Овчинников написал в свой блог длинную и популярную статью. На блог пришло очень много людей и стали внимательно всё читать. Пока каждый из пришедших человек читал статью, виджет с выручкой исправно работал и запрашивал API каждые 20 секунд.

API вызывало хранимую процедуру на расчет суммы всех заказов с начала года по всем пиццериям сети. Агрегация шла по таблице orders, которая очень популярна. В неё же ходят все кассы всех открытых ресторанов на тот момент. Кассы перестали отвечать, заказы не принимались. Ещё они не принимались с сайта, не появлялись на трекере, менеджер смены не мог увидеть их в своем интерфейсе.

Это не единственная история. К осени 2015 года каждую пятницу нагрузка на систему была критическая. Несколько раз мы выключали публичное API, а однажды, нам пришлось даже отключить сайт, потому что уже ничего не помогало. Был даже список сервисов с порядком отключения при серьезных нагрузках.

С этого времени начинается наша борьба с нагрузками и за стабилизацию системы (с осени 2015 до осени 2018). Именно тогда случилось Великое падение. Дальше тоже иногда происходили сбои, некоторые были весьма чувствительными, но общий период нестабильности сейчас можно считать пройденным.

Бурный рост бизнеса

Почему нельзя было сделать сразу хорошо? Достаточно посмотреть на следующие графики.

Также в 2014-2015 было открытие в Румынии и готовилось открытие в США.

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

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

Быстрые решения, которые помогли

Проблемы требовали решения. Условно, решения можно разделить на 2 группы:

  • Быстрые, которые тушат пожар и дают небольшой запас прочности и выигрывают нам время на изменения.

  • Системные и, поэтому, долгие. Реинжиниринг ряда модулей, разделение монолитной архитектуры на отдельные сервисы (большинство из них вполне не микро, а скорее макросервисы и про это есть доклад Андрея Моревского).

Сухой список быстрых изменений таков:

Scale up мастер базы

Конечно, первое, что делается для борьбы с нагрузками увеличивается мощность сервера. Это делали для мастер базы и для веб серверов. Увы, это возможно лишь до некоторого предела, дальше становится слишком дорого.

С 2014 года мы перешли в Azure, на эту тему мы тоже писали еще в то время в статье Как Додо Пицца доставляет пиццу с помощью облака Microsoft Azure. Но после череды увеличений сервера под базу уперлись по стоимости.

Реплики базы на чтение

Реплик для базы сделали две:

ReadReplica для запросов на справочники. Применяется для чтения справочников, типа, города, улицы, пиццерии, продуктов (slowly changed domain), и в тех интерфейсах, где допустима небольшая задержка. Этих реплик было 2, мы обеспечивали их доступность также, как и мастера.

ReadReplica для запросов на отчеты. У этой базы доступность была ниже, но в неё ходили все отчеты. Пусть у них тяжелые запросы на огромные пересчеты данных, но зато они не влияют на основную базу и операционные интерфейсы.

Кэши в коде

Кэшей в коде нигде не было (вообще). Это приводило к дополнительным, не всегда нужным, запросам в нагруженную базу. Кэши были сначала как в памяти, так и на внешнем кэш-сервисе, это был Redis. Все инвалидировалось по времени, настройки указывались в коде.

Несколько серверов для бэкэнда

Бэкэнд приложения тоже надо было масштабировать, чтобы выдерживать повышенные нагрузки. Необходимо было сделать из одного iis-сервера кластер. Мы перенесли сессию приложений из памяти на RedisCache, что позволило сделать несколько серверов, стоящих за простым балансировщиком нагрузки с round robin. Сначала использовался тот же Redis, что и для кэшей, потом разнесли на несколько.

В итоге архитектура усложнилась

но часть напряженности удалось снять.

А дальше нужно было переделывать нагруженные компоненты, за что мы и взялись. Об этом мы расскажем в следующей части.

Подробнее..

Выбор архитектурного стиля (часть 2)

17.09.2020 12:16:31 | Автор: admin
Привет, хабр. Сегодня я продолжаю серию публикаций, которую написал специально к старту нового потока курса Software Architect.



Введение


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

В прошлый раз мы разобрались с монолитом и пришли к тому, что монолит имеет ряд проблем: размер, связанность, развертывание, масштабируемость, надежность и косность.

В этот раз я предлагаю поговорить о возможностях организации системы в виде набора модулей/библиотек (компонентно-ориентированная архитектура) или сервисов (сервис-ориентированная архитектура).

Компонентно-ориентированная архитектура


Компонентно-ориентированная архитектура предполагает выполнение системы в виде набора компонентов, которые можно использовать как в текущем, так и в будущих проектах. При разбиении системы на компоненты учитываются: пригодность их для повторного использования, их замещаемость, независимость от контекста, расширяемость, инкапсуляцию и независимость.

При грамотном использовании компонентов решается проблема большого кома грязи (большой размер + высокая связанность), а сами компоненты могут представлять из себя как единицы сборки (модули, библиотеки), так и единицы развертывания (сервисы). Единицы развертывания не всегда отображаются на выполняемый процесс: например, веб-приложение и база данных развертываются совместно.

Наиболее часто монолиты разрабатываются в виде набора модулей. Такой подход приводит к обеспечению независимости разработки, но при этом проблемы независимых масштабирования и развертывания, отказоустойчивости и независимости от общего технологического стека остаются. Именно поэтому модуль частично независимая компонента.

Самая главная проблема такого монолита заключается в том, что разделение на модули является чисто логическим и может быть легко нарушено разработчиками. Может появиться модуль core, который постепенно превращается в помойку, может расти граф зависимостей между модулями и так далее. Для избежания таких проблем разработка должна вестить либо очень зрелой командой, либо под руководством архитектора, который на full time занимается code review и бьет нарушающих логическую структуру разработчиков по рукам.

Идеальный монолит представляет из себя набор логически разделенных модулей, каждый из которых смотрит в свою базу данных.

Сервис-ориентированная архитектура


Если все-таки предполагается организация системы в виде набора сервисов, то речь идет о сервис-ориентированной архитектуре. Ее принципы: сочетаемость приложений, ориентированных на пользователей, многократное использование бизнес-сервисов, независимость от набора технологий и автономность (независимые эволюция, масштабируемость и развертываемость).

Сервис-ориентированная архитектура (SOA = service oriented architecture) решает все обозначенные проблемы монолита: при изменении затрагивается только одна служба, а четко определенный API поддерживает хорошую инкапсуляцию компонент.

Но не все так гладко: SOA приводит к возникновению новых проблем. Удаленные вызовы дороже локальных, а перераспределение обязанностей между компонентами стало существенно дороже.

Кстати говоря, возможность независимого развертывания это очень важная особенность сервиса. Если сервисы должны развертываться совместно или, тем более, в определенной последовательности, то система не может считаться сервис-ориентированной. В таком случае говорят о распределенном монолите (считается антипаттерном не только с точки зрения SOA, но и микросервисной архитектуры).

Сервис-ориентированная архитектура неплохо поддерживается архитектурным коммьюнити и вендорами. Отсюда следует наличие множества курсов и сертификаций, хорошо проработанных паттернов. К последним относится, например, не безызвестная сервисная шина предприятия (ESB = enterprise service bus). При этом ESB это багаж от вендоров, она не обязательно должна использоваться в SOA.

Пик популярности сервис-ориентированной архитектуры приходился примерно на 2008 год, после чего она пошла на спад, который стал существенно более резким после появления микросервисов (~2015 год).

Заключение


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

Подробнее..

Выбор архитектурного стиля (часть 3)

28.09.2020 02:15:18 | Автор: admin
Привет, Хабр. Сегодня я продолжаю серию публикаций, которую написал специально к старту нового потока курса Software Architect.



Введение


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

В прошлый раз мы поговорили о различных видах монолитов и об использовании компонентов для их построения, причем как компонентов сборки, так и компонентов развертывания. Мы разобрались с сервис-ориентированной архитектурой.

Сейчас мы наконец определим основные характеристики микросервисной архитектуры.

Отношение архитектур


Необходимо понимать, что исходя из данных в предыдущих статьях определений любой сервис является компонентом, но не любой сервис является микросервисом.

Характеристики микросервисной архитектуры


Основными характеристиками микросервисной архитектуры являются:

Организация в соответствии с бизнес-возможностями
(Organized around Business Capabilities)
Продукты, а не проекты (Products not Projects)
Умные точки входа и глупые каналы (Smart endpoints and
dumb pipes)
Децентрализованное управление (Decentralized Governance)
Децентрализованное управление данными (Decentralized
Data Management)
Автоматизация инфраструктуры (Infrastructure Automation)
Страховка от сбоев (Design for failure)
Архитектура с эволюционным развитием (Evolutionary
Design)

1-ый пункт приходит от сервис-ориентированной архитектуры, потому что микросервисы являются частным случаем сервисов. Другие пункты заслуживают отдельного рассмотрения.

Организация в соответствии с бизнес-возможностями (Organized around Business Capabilities)


Сейчас необходимо вспомнить закон Конвея: организации, создающие системы, организуют ее архитектуру, копирующую структуру взаимодействия внутри этих организаций. В качестве примера можно вспомнить случай создания компилятора: команда из семи человек разработала семипроходный компилятор, а команда из пяти пятипроходный.

Если мы говорим про монолиты и микросервисы, то в том случае, если разработка организована по функциональным отделам (бэкенд, фронтенд, администраторы баз данных), то получается классический монолит.

Для получения микросервисов команды необходимо организовывать по бизнес-возможностям (команда заказов, отгрузок, каталога). Такая организация даст возможность командам сосредоточиться на создании конкретных частей приложения.

Продукты, а не проекты (Products not Projects)


Проектный подход при котором команда передает разработанную функциональность другим командам в случае микросервисной архитектуры совершенно не подходит. Команда должна поддерживать систему на протяжении всего ее жизненного цикла. Компания Amazon, один из флагманов внедрения микросервисов, заявляла: вы создаете продукт, и вы же запускаете его (you build, you run it). Продуктовый подход позволяет команде почувствовать потребности бизнеса.

Умные точки входа и глупые каналы (Smart endpoints and dumb pipes)


SOA архитектура большое внимание уделяла каналам связи, в частности Enterprise Service Bus (сервисная шина предприятия). Что зачастую приводит к Erroneous Spaghetti Box, то есть сложность монолита переходит в сложность связей между сервисами. В микросевисной архитектуре используются только простые способы взаимодействия.

Децентрализованное управление (Decentralized Governance)


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

Децентрализованное управление данными (Decentralized Data Management)


Стандартный подход, в котором приложение опирается на одну базу данных, не может учитывать специфики каждого конкретного сервиса. MSA предполагает децентрализованное управление данными, вплоть до применения различных технологий.

Автоматизация инфраструктуры (Infrastructure Automation)


MSA поддерживает процессы непрерывного развертывания и поставки. Осуществить это возможно только путем автоматизации процессов. При этом, развертывание большого количества сервисов уже не выглядит чем-то страшным. Процесс развертывания должен стать скучным. Второй аспект связан с управлением сервисами в продуктовой среде. Без автоматизации, управление процессами, запущенными в разных операционных средах, становится невозможным.

Страховка от сбоев (Design for failure)


Многочисленные сервисы MSA подвержены сбоям. При этом, обработка ошибок в распределенной системе весьма не тривиальная задача. Архитектура приложений должна быть устойчива к таким сбоям. Ребекка Парсонс считает очень важным, что мы больше не используем даже внутрипроцессное взаимодействие между сервисами, вместо этого для связи мы прибегаем к HTTP, который и близко не бывает столь же надёжен.

Архитектура с эволюционным развитием (Evolutionary Design)


Архитектура MSA системы должна развиваться эволюционно. Желательно ограничить необходимые изменения границами одного сервиса. Необходимо так же учитывать влияние на другие сервисы. Традиционный подход состоит в том, чтобы попытаться решить эту проблему с помощью управления версиями, но MSA предполагает использовать управление версиями в
качестве крайней меры.

Заключение


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



Читать часть 2
Подробнее..

Выбор архитектурного стиля. Часть 4

12.10.2020 16:11:28 | Автор: admin
В конце октября запускаем новую группу курса Архитектура и шаблоны проектирования и приглашаем всех специалистов на бесплатный Demo-урок Шаблон адаптер, который проведёт Матвей Калинин главный разработчик в одном из крупнейших банков страны.




Введение


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

В прошлый раз мы сформулировали понятие микросервиса и определили основные положения, отличающие микросервисную архитектуру от сервис-ориентированной.

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

Проблема выбора


На самом деле, микросервисная архитектура не является серебрянной пулей: она решает вполне конкретные задачи и влечет большое количество проблем, которые возникают наравне с преимуществами этого архитектурного стиля.

Независимое развертывание


С одной стороны, в микросервисной архитектуре нет нужды координировать поставку и развертывание разного функционала. Таким образом обеспечивается быстрй запуск, а сбой при развертывании не приводит к отказу системы. Каждая служба может быть развернута в том количестве, которое действительно необходимо, а специализация сервисов позволяет предоставлять им только необходимые ресурсы.

С другой стороны, в связи с большим количеством разнородных компонент, процесс развертывания в целом становится достаточно сложным и требует автоматизации. Кроме того усложняются процессы тестирования и сопровождения. Переход от гигантских мэйнфреймов к множеству слабых машин приводит к сетевым проблемам, а соединение по сети медленно и ненадежно.

Улучшение отказоустойчивости


Возможность независимого масштабирования и развертывания позволяет повышать избыточность отдельного сервиса и при необходимости перезапускать его без остановки всей системы.

Но при этом необходимо учитывать то, что каждый сетевой вызов может закончится неудачей любая служба, с которой вы взаимодействуете, может перестать отвечать. Кроме этого распределение данных в сети делает проблемой обеспечение согласованности данных.

Гибкость и ясность


Жесткие физические границы сервиса обеспечивают низкую связанность, хорошо управляемые части, их независимую разработку. Разработчики хорошо понимают свою часть системы.

Но, независимость разработчиков приводит к эффекту колодца, когда никто не видит картины целиком.

Варьирование технологического стека


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

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

Техническая сложность


Исходя из всего вышесказанного можно сделать вывод, что разработка микросервисов является достаточно сложной технической задачей, требующей особых навыков разработчиков, технических специалистов (DevOps) и тестировщиков. А так же, что самое главное, определенной организационной перестройки и смены парадигмы мышления у отдельных индивидуумов.

Распространенные заблуждения


С микросервисной архитектурой связан ряд заблуждений. Вот некоторые из них:
  1. Код будет чище. Код не будет чище, если не будут предприняты усилия, чтобы код стал чище.
  2. Писать модули, решающие одну задачу легче.
    Не легче, поскольку у таких модулей будет очень много интеграций.
  3. Это работает быстрее, чем монолит.
    Монолит работает быстрее из-за меньшего количества сетевых вызовов.
  4. Инженерам проще, если не нужно работать с единой кодовой
    базой.
  5. Это самый простой способ обеспечить автоматическое
    масштабирование.
  6. И тут где-то замешан Докер.


Заключение


На этой радостной ноте предлагаю закончить. В следующий раз поговорим о том, когда стоит применять такой архитектурный стиль как микросервисная архитектура.

image
Подробнее..

Суровая правда о разработчиках и разработке

10.02.2021 16:11:31 | Автор: admin

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

Огромных зарплат в те времена не было, компании по разработке ПО создавались романтиками в съемных комнатушках-офисах, в которых часто приходилось и ночевать. Кто-то не выдерживал и сдавался, кто-то создавал шедевры и богател, но в те времена никто не говорил, что люди получают зарплату просто так. Те времена подарили нам кучу программ, часть из которых остаются самыми популярными в своей сфере и по сей день (Например, MS Excel. Страшно думать, но до сих пор большинство инвестиционных банкиров используют для своих моделей именно MS Excel). Те времена подарили нам таких людей как Питер Нортон и Андерс Хейлсберг или Джон Кармак с Сидом Майером, если игры вам ближе.


В конце 90х, с повсеместным развитием интернета, стали проявляться первые тревожные звоночки. Зарплаты разработчиков стали расти вместе с акциями доткомов, этот пузырь стал притягивать к себе любых людей, способных написать хоть какой-то код. Вместо людей, прекрасно знающих свою область стали появляться случайные люди, которые хоть как-то справлялись с поставленными задачами. Единственным плюсом, наверное, был тот факт, что пока еще эти ребята не диктовали бизнесу, как он должен работать.

Доткомы благополучно умерли и лет на десять чума современной разработки исчезла, чтобы вернуться в начале десятых годов 21 века с новой силой. Укоренившийся в жизни интернет привел к тому, что любой конторке больше пяти человек стал требоваться сайт (а лучше портал) и потребность в разработчиках (а, следовательно, и зарплаты) стала расти. В России за пять лет зарплаты выросли с 200 долларов до тысячи и десятки тысяч молодых специалистов принялись штурмовать новые горизонты.

Команды росли, сложность решений росла, люди, основавшие бизнес, постепенно стали отходить от дел и перестали контролировать какие-либо процессы разработки, в результате чего разработка фактически превратилась в вещь в себе. Отдельную отрицательную роль в этом процессе сыграли гиганты IT рынка типа Гугла, который возвел практику работы на корзину в ранг нормы, паразитируя на традиционном бизнесе и вливая кучу денег в решения, не имеющие какого-либо смысла. Люди, принимающие решения по ИТ, стали везде пихать опыт FAANG всюду и везде, давя авторитетом Что вы будете спорить с компаниями, зарабатывающими сотни миллиардов?. Стоимость разработки продолжала расти, хотя никакого прорыва в технологиях с начала двухтысячных не произошло.

Почему растет стоимость разработки? Ответ, на самом деле, тут прост и банален. Бизнес слабо понимает, что происходит в разработке, а разработка на самом деле работает сама на себя, делая то, что нравится, а не то, что надо, попутно внедряя в процесс кучу лишних людей. Разработчикам нравятся новые технологии, и они пытаются впихнуть их везде, где им дадут. Например, в моей текущей компании на хайпе стали внедрять BigData обосновывая это возможностью тонкой настройки бизнеса. Знаете, к чему это привело? Сотни миллионов денег были потрачены на то, чтобы сказать, что товары, которые покупают на точке в дорогом ТК в центре отличаются от товаров, покупаемых на окраине рядом с ЖД станцией. Серьезно? Вы потратили такой бюджет на то, чтобы найти факты, которые очевидны любому, кто занимался ритейлом? Другое прорывное решение касалось в определении людей, кто часто бывает рядом и предложении им семейных контрактов. О да, тут точно нужна BigData, без нее никак. Отдельная команда целый год пилила очень нужный в 2018 году блокчейн для голосовалок. Никто понятия не имеет, как его можно использовать в текущем бизнесе, но раз деньги выделяют, то почему бы и нет? Мы же не можем отставать по инновациям от Сбера? А Сбер не может отставать от Гугла?

Отдельно упоминания, безусловно, стоят микросервисы и контейнеры, которые пихают везде и вся. Попробуйте в 2021 году пойти на собеседование и сказать, что вы не понимаете, зачем нужны микросервисы. Вас поднимут на смех! Скажут: А как же хайлоад?, А как же независимые команды?, А как же отдельные стэки?.

Ты пытаешься выяснить, что же за хайлоад. На проверку оказывается, что там 200 запросов в секунду в пике. Ребята, Asp.Net Core + MVC + EF + PG держит 185 тысяч запросов в секунду single-query. Какой у вас хайлоад? И да, все еще забывают, что количество запросов к нагрузке также имеют очень маленькое отношение. В случае того же Твитера нет никаких бизнес-критичных запросов, мы можем ставить сотни одинаковых инстансов и проксировать запросы как душе угодно, никто не пострадает. Это вам даже не Букинг какой-нибудь, где на последний номер может быть несколько желающих.

Другой веселый юмор это независимые команды. Сидят, значит двадцать человек. И они никак не могут поделить обязанности, чтобы не мешать друг-другу. Тут значит, они начинают пилить 4 микросервиса по 5 человек в команде и волшебным образом сразу проблемы все решаются. Да нет же, проблемы не решатся. Их станет в разы больше. Вот тут хорошо написано. Вам будет сложнее выделять домены, тестировать, деплоить. Вам даже просто понадобиться куча дополнительных людей высокой квалификации, начиная от архитектора, кончая тестировщиками с девопсами.

Отдельная песня это возможность команде самой определять стэк, на которой ей удобно работать. Ну вы знаете, тот знаменитый подход, который приводит к командам на Java, Go, C++, Rust и NodeJS на одном бизнес-проекте. Причем вместе с несколькими SQL и NoSQL одновременно. Так ведь удобно потом нанимать разработчиков на каждый из стэков и поддерживать кодовую базу в актуальном состоянии. Так удобно следить за безопасностью сотен пакетов на каждый из фреймвороков. Так приятно, когда один и тот же код для интеграций с системами аутентификации или мониторинга повторяется на каждом фреймворке заново. Так удобно иметь отдельные конвейеры CI/CD и команду поддержки под каждый стэк. Нет, если вы Гугл и у вас есть десятки тысяч инженеров хорошей квалификации, которым по факту нечего делать, то подход имеет право на существование. Но если вы не Гугл, то зачем повторять худшие практики?

Ну и вишенка на торте это лишние люди в конвейере производства программного обеспечения. Да, вот эти ребята, типа скрам мастера или эджайл коуча. Как-же без них удавалось спутники запускать и ММОРПГ создавать? Современные команды ведь настолько профессиональны и заточены на результат что никак не могут самостоятельно оценить и распределить таски, им обязательно нужны пара нянек.

Я сам получаю деньги за то, что пишу код с 2006 года, в этом году будет 15 лет юбилея. И мне очень горько понимать, что моя любимая отрасль, которая подарила множество прекрасных продуктов, технологий или игр превратилась в огромного паразита, который воспроизводит сам себя и пытается высосать все соки. Сложно сказать, кто в этом виноват и когда свернули не туда. Факт состоит в том, что современное IT скорее тянет на дно бизнес, чем помогает ему развиваться. Все современные IT гиганты делали свое имя много лет назад при помощи других людей. Да, современный бизнес невозможен без IT. Но все забывают, что IT это прежде всего поддерживающее звено, а не основа мироздания. Какими бы не были прорывные технологии, условный Нетфликс все-таки будет оцениваться качеством контента.

Что делать?

Хотелось бы прояснить, почему вообще у меня пригорает на тему ситуации в IT. Как-то сложилось, что за свою жизнь я был активным пользователем IT продуктов. И уже не первый год, как я стал замечать, что качество продуктов, падает год к году. Яснее всего это видно, конечно же, в игрострое. Все идеи, которые успешно доят до сих пор появились лет 20-30 назад. MVP сего парада стал безусловно Warcraft 3: Reforged и Star Citizen. Однако нельзя сказать, что и в других отраслях таких проблем нет. Качество поиска Гугла стабильно падает. Фейсбук редизайнит так, что лучше бы вообще не трогал. И все это при том, что разработчиков в штате компаний все больше и больше.

В качестве решения накопленных проблем мне лично видятся следующие меры:

  • Переход от экстенсивного развития к интенсивному: пересмотр бизнес-процессов в сторону упрощения, снижение количества регламентов;

  • Упрощение процесса разработки за счет более простых и эффективных бизнес процессов и прозрачной системы принятия решений;

  • Использование в рамках компании стандартных стеков технологий и пакетов;

  • Формирование центров компетенций разработки для поддержания актуальности стэков технологий, формирования стандартных шаблонов проектов компании и архитектур;

  • Подбор оптимальной архитектуры под бизнес требования;

  • Сокращение time-to-market за счет активного переиспользования кодовой базы, шаблонов и простой архитектуры;

  • Сокращение людей не увеличивающих ценность продуктов, таких как скрам мастер, эджайл коуч и прочих.

Если все это не сделать в ближайшее время и не повысить эффективность разработки, то есть высокая вероятность, что IT потянет на дно компании и нас будет ждать второй пузырь доткомов.

А что Вы думаете о текущем этапе развития IT. Какие проблемы видите лично Вы, насколько они кажутся серьезными и как их лучше решать?

Подробнее..

Перевод Как справиться с более чем двумя миллиардами записей в SQL-базе данных

22.03.2021 18:15:22 | Автор: admin

В рамках набора группы учащихся на курс "Highload Architect" подготовили перевод интересной статьи.

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


У одного из наших клиентов возникла проблема с большой, постоянно растущей, таблицей в MySQL с более чем 2 миллиардами записей. Без модернизации инфраструктуры была опасность исчерпания дискового пространства, что потенциально могло сломать все приложение. С такой большой таблицей были и другие проблемы: низкая производительность запросов, плохая схема, и, из-за огромного количества записей, не было простого способа анализировать эти данные. Также нам нужно было решить эти проблемы без простоев в работе приложения.

В этом посте я хотел рассказать о нашем подходе к данной проблеме, но сразу хочу оговориться, что это не универсальное решение: каждый случай индивидуален и требует разных подходов. Но, возможно, вы найдете здесь некоторые полезные идеи для себя.

Спасение в облаках

После оценки нескольких альтернативных решений мы решили отправлять данные в какое-нибудь облачное хранилище. И наш выбор пал на Google Big Query. Мы выбрали его, потому что клиент предпочитал облачные решения от Google, а также данные были структурированными, предназначались для аналитики и нам не требовалась низкая задержка передачи данных (low latency). Поэтому BigQuery, казалась, идеальным решением (см. диаграмму ниже).

После тестов, о которых вы можете прочитать в посте Анджея Людвиковски (Andrzej Ludwikowski), мы убедились, что Big Query достаточно хорошее решение, отвечающее потребностям наших клиентов и легко позволяет использовать аналитические инструменты для анализа данных. Но, как вы, возможно, уже знаете, большое количество запросов в BigQuery может привести к увеличению стоимости, поэтому мы хотели избежать запросов в BigQuery напрямую из приложения и использовать его только для аналитики и как что-то вроде резервной копии.

https://cloud.google.com/solutions/infrastructure-options-for-data-pipelines-in-advertising#storing_data

Передача данных в облако

Для передачи потока данных есть много разных способов, но наш выбор был очень прост. Мы использовали Apache Kafka просто потому, что она уже широко использовалась в проекте и не было смысла внедрять другое решение. Использование Kafka дало нам еще одно преимущество мы могли передавать все данные в Kafka и хранить их там в течение необходимого времени, а затем использовать для миграции в выбранное решение, которое справилось бы со всеми проблемами без большой нагрузки на MySQL. С таким подходом мы подготовили себе запасной вариант в случае проблем с BigQuery, например, слишком высокой стоимости или сложностей и с выполнением необходимых запросов. Как вы увидите ниже, это было важное решение, которое дало нам много преимуществ без каких-то серьезных накладных расходов.

Потоковая передача из MySQL

Итак, когда речь заходит о передаче потока данных из MySQL в Kafka, вы, вероятно, думаете о Debezium или Kafka Connect. Оба решения отличный выбор, но в нашем случае не было возможности их использовать. Версия сервера MySQL была настолько старой, что Debezium ее не поддерживал, а обновление MySQL было невозможным. Мы также не могли использовать Kafka Connect из-за отсутствия автоинкрементного столбца в таблице, который мог бы использоваться коннектором для запроса новых записей без потери каких-либо из них. Мы знали, что можно использовать timestamp-столбцы, но при этом подходе могли быть потери строк из-за того, что запрос использовал более низкую точность timestamp, чем указано в определении столбца.

Конечно, оба решения хороши, и если нет никаких препятствий для их использования, то я могу рекомендовать их для передачи данных из вашей базы данных в Kafka. В нашем случае нам нужно было разработать простого Kafka Producer, который запрашивал данные без потери каких-либо записей и передавал их в Kafka. И Kafka Consumer, отправляющего данные в BigQuery, как показано на диаграмме ниже.

Отправка данных в BigQueryОтправка данных в BigQuery

Секционирование как способ экономии места

Итак, мы отправили все данные в Kafka (сжимая их для уменьшения полезной нагрузки), а затем в BigQuery. Это помогло нам решить проблемы с производительностью запросов и быстро анализировать большой объем данных. Но осталась проблема с доступным местом. Мы хотели найти решение с заделом на будущее, которое справилось бы с проблемой сейчас и могло быть легко использовано в будущем. Мы начали с разработки новой таблицы. Мы использовали serial id в качестве первичного ключа и секционирование по месяцам. Секционирование этой большой таблицы дало нам возможность создавать резервные копии старых секций и усекать (truncate) / удалять (drop) их, чтобы освободить место, когда секция больше не нужна. Итак, мы создали новую таблицу с новой схемой и использовали данные из Kafka для ее заполнения. После переноса всех записей мы развернули новую версию приложения, которая для INSERT использовала новую таблицу с секционированием и удалили старую, чтобы освободить место. Конечно, вам понадобится достаточно свободного места для переноса старых данных в новую таблицу, но в нашем случае во время миграции мы постоянно делали резервные копии и удаляли старые разделы, чтобы быть уверенными, что у нас хватит места для новых данных.

Передача данных в секционированную таблицуПередача данных в секционированную таблицу

Сжатие данных как еще один способ освободить пространство

Как я уже упоминал, после передачи данных в BigQuery мы могли легко анализировать их, и это дало нам возможность проверить несколько новых идей, которые могли бы позволить нам уменьшить пространство, занимаемое таблицей в базе данных.

Одна из идей была посмотреть, как различные данные распределены по таблице. После нескольких запросов выяснилось, что почти 90% данных никому не нужны. Поэтому мы решили их сжать, написав Kafka Consumer, который отфильтровал бы ненужные записи и вставлял только нужные в еще одну таблицу. Назовем ее сжатой таблицей (compacted table), что показано на приведенной ниже диаграмме.

После сжатия (строки со значением "A" и "B" в колонке type были отфильтрованы во время миграции).

Передача данных в compacted-таблицуПередача данных в compacted-таблицу

После этого мы обновили наше приложение и теперь выполняли чтение из новой таблицы (compacted table), а запись делали в секционированную таблицу (partitioned table), из которой мы непрерывно передавали данные с помощью Kafka в сжатую таблицу (compacted table).

Итак, как видите, мы устранили проблемы, с которыми столкнулся наш клиент. Благодаря секционированию была устранена проблема нехватки места. Сжатие и правильное проектирование индексов решили некоторые проблемы с производительностью запросов из приложения, и, наконец, передача всех данных в облако дала нашему клиенту возможность легко анализировать все данные.

Так как мы используем BigQuery только для аналитических запросов, а остальные запросы, отправляемые пользователями через приложение, по-прежнему выполняются в MySQL, то затраты оказались не такие и большие, как можно было бы ожидать. Еще одна важная деталь все было выполнено без простоев, ни один клиент не пострадал.

Резюме

Итак, подведем итоги. Мы начали с использования Kafka в качестве инструмента для потоковой передачи данных в BigQuery. Но так как все данные были в Kafka, это дало нам возможность легко решить другие проблемы, которые были важны для нашего клиента.


Узнать подробнее о курсе "Highload Architect".

Смотреть вебинар на тему Выбор архитектурного стиля.

Подробнее..

Перевод Как создать архитектуру для работы с высокой нагрузкой вашего веб-проекта?

26.05.2021 16:17:30 | Автор: admin

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

Помните "Черные Пятницы", которые так популярны среди людей? Знаете ли вы, что иногда сайты и веб-приложения не выдерживают такого огромного наплыва пользователей и в результате этого нередко теряют много денег?

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

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

Ознакомьтесь с некоторыми фактами о высокой нагрузке:

  • Высокая нагрузка возникает, когда один физический сервер становится не в состоянии эффективно выполнять обработку данных.

  • Если один экземпляр (instance) одновременно обслуживает 10 000 соединений - это высокая нагрузка. Высокая нагрузка - это одновременное обслуживание тысяч и миллионов пользователей

  • Если вы развертываете веб-решение на AWS (Amazon Web Services), Microsoft Azure или Google Cloud Platform, вы поддерживаете архитектуру для работы с высокой нагрузкой.

Вы можете столкнуться со следующими проблемами, если ваше веб-решение не выдерживает высоких нагрузок:

  • Медленная или бесконечная загрузка страниц

  • Случайные ошибки

  • Разрывы соединений с веб-сервером

  • Неполная загрузка контента

  • Снижение активности пользовательской аудитории

  • Потери клиентов

Как видите, архитектура проекта влияет на его успешность. Нет довольных клиентов - нет успеха и прибыли. Чтобы реализовать масштабируемые веб-приложения, необходимо понимать принципы разработки высокопроизводительных программных решений.

Принципы построения высокоэффективных решений

Динамика и гибкость

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

Либо потребуется добавить различные функции. А может вы решите продвигать свое приложение и привлекать клиентов. Поэтому вы должны обеспечить возможность эластичного масштабирования и обработки высоких нагрузок.

При разработке крупномасштабных веб-решений уделяйте особое внимание гибкости, так как это позволит вам легко вносить изменения и расширения. Гибкость, отсутствие предварительного планирования всех аспектов - важнейшая характеристика любой быстрорастущей программной системы.

Постепенный рост проекта

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

Если вы запускаете новый продукт, нет смысла сразу же создавать инфраструктуру, способную выдержать миллионы пользователей и одновременно обрабатывать их многочисленные запросы.

Используйте облако для размещения новых проектов, поскольку оно позволяет снизить стоимость сервера, упрощает управление им и легко развертывает приложения.

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

Масштабирование веб-решения - это постепенный процесс, состоящий из 4 основных этапов:

  • Анализ нагрузки

  • Определение областей, на которые в основном воздействует нагрузка

  • Передача этих областей отдельным узлам и их оптимизация

  • Анализ нагрузки

Разработка масштабируемой архитектуры веб-проекта

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

Такой подход поможет вам сэкономить время и снизить затраты на разработку. Ниже представлены некоторые способы, которые помогут вам создать высокопроизводительные масштабируемые веб-приложения.

Разделение базы данных

Чаще всего первым узлом, который подвергается нагрузке, является база данных. Каждый запрос от пользователя к приложению - это, как правило, от 10 до 100 запросов к базе данных. Вынесение базы данных на отдельный сервер повысит ее производительность и снизит негативное воздействие на другие компоненты (PHP, Nginx и т.д.).

Миграция базы данных

В некоторых случаях перенос базы данных на другой сервер может стать проблемой для работающего веб-решения. Для эффективного переноса необходимо сделать следующее:

  • Используйте простое решение - разместите объявление о планируемых работах на сайте и сделайте перенос. Лучше сделать это ночью, когда активность пользовательской аудитории минимальна.

  • Используйте репликацию для синхронизации данных с одного сервера на другой. После настройки необходимо изменить IP-адрес базы данных в приложении на новый сервер. Затем - выключить старый сервер.

Разделение веб-сервера

Далее следует отделить веб-сервер, выделение которого на отдельный узел позволит оставить больше ресурсов для приложения. Если говорить о примере с PHP, то необходимо настроить развертывание продукта как на сервер Nginx, так и на сервер PHP, представляющий бэкенд.

Тогда Nginx сам отдаст статические файлы, а PHP-сервер будет занят только обработкой скриптов. Nginx обеспечивает подключение к бэкенду по IP-адресу:

server {server_name ruhighload.com;root /var/www/ruhighload;index index.php;location ~* .(php)$ {fastcgi_pass 10.10.10.1:9000;fastcgi_index index.php;include fastcgi_params;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;}}

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

Используйте несколько бэкендов

Когда нагрузка возрастает, веб-приложение начинает работать медленнее. В какой-то момент причина будет заключаться уже в самой имплементации. Чтобы избежать подобных проблем, следует использовать несколько бэкендов PHP.

При инсталляции бэкендов убедитесь, что они имеют одинаковую конфигурацию. Используйте Nginx для балансировки нагрузки между ними. Для этого следует определить список бэкендов в апстрим (upstream) и использовать его в конфигурации:

upstream backend {server 10.10.10.1;server 10.10.10.2;server 10.10.10.3;}server {server_name ruhighload.com;root / var / www / ruhighload;index index.php;location ~ * . (php) $ {fastcgi_pass backend;fastcgi_index index.php;include fastcgi_params;fastcgi_param SCRIPT_FILENAME $ document_root $ fastcgi_script_name;}}

Когда вы начнете использовать несколько бэкендов, запросы от одного и того же пользователя будут отправляться на разные серверы. Это потребует единого репозитория для всех сессий.

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

Очереди задач и балансировка DNS

Очереди задач позволяют асинхронно выполнять тяжелые операции, не замедляя работу основного приложения. Пока сервер очереди будет получать задания от веб-решения, другие серверы будут их обрабатывать. Если среднее количество задач в очереди будет расти, увеличьте количество серверов для балансировки нагрузки.

DNS поддерживает балансировку по принципу Round Robin, позволяя указать несколько IP-адресов принимающих веб-серверов, называемых фронтендами. В данном случае необходимо инсталлировать несколько одинаковых фронтендов, чтобы DNS выдавал разные IP-адреса разным клиентам. Таким образом, вы обеспечите балансировку между фронтендами.

Файловые хранилища

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

Более того, это может снизить производительность бэкенда. Чтобы избежать подобных трудностей, следует использовать отдельные серверы для загрузки, хранения и обработки файлов.

Сделать это можно следующим образом:

  • Определить отдельный поддомен для файлового сервера.

  • Развернуть на сервере Nginx и небольшое приложение, которое может хранить файлы и обрабатывать их

  • Масштабирование путем добавления новых серверов и поддоменов (например, images1, images2, images3 и т.д.)

  • Перенести загрузку файлов на сторону клиента, чтобы форма отправляла запрос на определенный сервер.

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

Однако ключевым моментом является экономическая эффективность. Скажем, у вас 100 тысяч пользователей и один сервер. Значит, чтобы получить 130 тысяч из них, нужно разместить еще один сервер. Кажется, что это довольно сложно, не так ли?

Поэтому следует сделать один шаг назад и подумать - какая часть системы вызывает проблему? Если это база данных, то перед началом разработки проекта выберите высокомасштабируемую базу данных. Или вы можете использовать несколько баз данных, например, одну для записи и одну для чтения (CQRS).

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


Перевод материала подготовлен в рамках запуска курса "Highload Architect".

Всех желающих приглашаем на бесплатный демоурок Выбор архитектурного стиля (микросервисы, СОА и монолиты).

- ЗАПИСАТЬСЯ НА ДЕМОУРОК

Подробнее..

Микросервисы не способ масштабироваться

28.05.2021 00:20:41 | Автор: admin

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

Что лучше: монолит или микросервис?

Рассмотрим пример.

Допустим, у нас есть микросервис A, выполняющий авторизационные запросы "имеет ли право пользователь выполнить операцию?".

Поскольку изолированно такой микросервис существовать не может, то в паре с ним существует другой микросервис B, который сохраняет в хранилище список соответствий пользователи-права (Фактически это структура одного микросервиса, разделённого на два, чтоб распределить нагрузку по логическим подмодулям. То есть деление даже более мелкое, нежели обычные микросервисы).

Примерная схема микросервисов показана на рисунке:

Рисунок 1Рисунок 1

В результате изменений в пользовательских данных (регистрация новых пользователей, ограничения на существующих и т.п.) микросервис B "следит" за актуальностью данных в хранилище, которое использует микросервис A для выполнения авторизационных запросов.

Простая схема. Просто устроена, надёжно работает.

Предположим, что количество пользователей, подключающихся к нашей системе, растёт. Каковы "узкие" места в этой архитектуре?

  • нагрузка на CPU в микросервисе A

  • нагрузка io-read/select в БД

  • нагрузка на CPU в микросервисе B

  • нагрузка io-write в БД

Вопросы с CPU в микросервисах решаются просто добавлением экземпляров в игру. Здесь масштабирование простое, и не стоит его обсуждать:

Рисунок 2Рисунок 2

Давайте посмотрим, что будет с ростом нагрузки на микросервис A и B?

В определённый момент времени БД перестанет справляться с потоком запросов на чтение от микросервиса A. При наступлении этих проблем обычно вводят в игру RO-реплики БД:

Рисунок 3Рисунок 3

Поскольку микросервис A не модифицирует записи в БД, то добавлением реплик к БД можно решить практически все вопросы масштабирования этого микросервиса.

Но вот вопрос: а что делать, когда микросервис B приведёт master-БД к лимиту, определённому максимумом нагрузки на запись (io-write)?

Вариантов решения этих проблем довольно немного. Все они сводятся к тому, чтоб распределить запись в БД по нескольким хостам. Используем схему шардинга или иной масштабируемый multi-master:

Рисунок 4Рисунок 4

Вместо одной БД у нас имеется X шардов БД, позволяющих масштабировать нагрузку на запись, и к каждому шарду - реплики (всего - Y), позволяющие масштабировать нагрузку на чтение.

Итого:

По мере роста нагрузки в нашем примере сами микросервисы претерпели немного изменений. Большинство изменений при масштабировании было в хранилище данных.

Если рассмотреть более обобщённо, то при масштабировании микросервисная архитектура сталкивается со следующими проблемами масштабирования:

  1. Ограничения CPU на хостах

  2. Ограничения IO в хранилищах данных

  3. Ограничения пропускной способности сети между хостами

Способы преодоления этих проблем масштабирования ничем не отличаются от способов, применяемых в немикросервисных архитектурах. Мало того, третья проблема встречается в основном именно в микросервисной архитектуре.

Выводы

  1. Микросервисная архитектура не является способом масштабирования проекта. Микросервисная архитектура - это способ разделения проекта на модули и инкапсуляции кода (и данных).

  2. Основу масштабирования практически любого большого проекта следует искать в области хранения и обработки хранящихся данных.

Монолиты и микросервисы: граница

Если рассмотреть развитие аналогичного монолитного сервиса примерно в таком же ключе, как мы рассматривали выше развитие микросервиса, то в результате его развития будут пройдены те же стадии преодоления проблем. В итоге структура монолита будет включать в себя те же самые компоненты. А если взглянуть на серверное разделение, то будут включать в себя выделенный сервер (кластер серверов) авторизации и сервер регистрации пользователей. Однако, эта структура будет оставаться монолитной.

В чём же отличие? Почему монолит, разделённый на сервисы, остаётся монолитом? Потому что во всех его сервисах используется единая кодовая база.

Если один и тот же код, не будучи выделен в библиотеку, работает во множестве микросервисов, то это - монолитная архитектура.

Построение проектов с нуля: Монолит vs микросервис

Если не рассматривать вновь запускаемые проекты на лямбдах/FaaS, то можно отметить одну чуть ли не во всех проектах встречающуюся особенность:

Как правило, проект на стадии запуска реализации и на стадии запуска MVP отличается довольно сильно. Видение бизнес-развития проекта в стадии после MVP отличается от стартового ещё сильнее. И, чем больше времени проект развивается, тем сильнее эти отличия.

Бизнес-требования к стартующему проекту обычно меняются прямо в процессе реализации его MVP. Да, это не для всех случаев так, но для огромного пула стартапов это именно так.

Что из этого следует? Из этого следует эмпирическое правило: для запуска стартапов необходимо выбирать технологии, исходя из критериев:

  • в дальнейшем понятно, как масштабировать (в основном, это относится к хранилищу)

  • сравнительно просто рефакторить (это относится к выбору технологии построения кода)

  • простое покрытие автоматическими тестами

Для рефакторинга и простоты покрытия тестами монолиты подходят идеально - позволяют работать в режиме "сперва взлетаем, а затем думаем о том, какие крылья нам лучше использовать".

И, исходя из написанного, энергию вечного спора "монолит vs микросервис" на стадии запуска проекта надо направить в русло проработки хранилища данных с изначальной ориентацией на масштабирование. А в процессе развития монолит и микросервис будут иметь весьма похожую архитектуру. Настолько похожую, что отличить их друг от друга будет сложно.

Подробнее..

Скрытые расходы при переходе на микросервисы

03.12.2020 12:07:50 | Автор: admin

В идеальном мире можно просто взять исходный код монолита, разделить его код между микросервисами и, соединив их между собой, получить ту же систему, но на новой архитектуре. В жизни так не происходит никогда. Жизнь вносит множество сложностей в эту идеальную картинку. Какие конкретно сложности могут увеличить бюджет перехода на микросервисы в два-три раза?

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

С этой темой я выступал на ArchDays 2020. По ссылке вы найдете слайды и видео (скоро будет опубликовано) выступления https://blog.byndyu.ru/2020/12/archdays-2020.html.

1 Изменение подхода к работе с мастер-данными

У монолита обычно есть одна или две большие базы данных, содержащие в себе разношерстные мастер-данные. В самом монолите написан код, который управляет этими мастер-данными. Например, если "зеленая" часть базы данных это адресный справочник, то "зеленый" код монолита управляет адресами. Получается в базе данных монолита множество мастер-данных, а в коде монолита много мастер-систем:

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

Четкое разграничение мастер-данных и мастер-систем по микросервисам нужно закладывать в оценку перехода. Занимает такая работа довольно много времени, которое уходит на следующее:

  1. анализ схемы данных монолита,

  2. анализ потоков обработки данных,

  3. анализ использования данных сторонними системами,

  4. бизнес-цели компании по работе с данными,

  5. "нарезка" данных по новым базам,

  6. миграция данных в новые базы микросервисов,

  7. тестирование миграции.

Четыре основные стратегии работы с мастер-данными описаны в статье Управления мастер-данными в микросервисной архитектуре.

Как и остальные 9 факторов, переработку мастер-данных нужно оценивать и учитывать в бюджете перехода на микросервисы еще до старта перехода.

2 Невозможность переиспользования исходного кода монолита

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

Практика показывает, что границы ответственности так или иначе растекаются внутри монолита. Из-за этого не получается использовать "копипаст" из монолита для заполнения микросервиса кодом. Весь код и тесты придется написать с нуля для правильного разделения ответственностей по микросервисам.

Если случилось чудо и код монолита окажется идеально написан (чего никогда не происходит), то всё равно этот код придется дописывать и переписывать под требования микросервисной архитектуры и под изменения в инфраструктуре (см. п.4).

Не поддавайтесь на оптимизм владельца продукта и разработчиков монолита. Закладывайте столько времени своих разработчиков и тестировщиков, как если бы вы писали систему с нуля, а не просто переносили готовый код из одного места в другое. Кроме этого, до начала работ желательно договориться с командой, писавшей монолит, чтобы они выделили время на ваши вопросы по коду.

3 Проектирование системы заново

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

Запланируйте время IT-архитектора, бизнес-аналитиков и стейкхолдеров на анализ бизнес-требований. Кроме этого, запланируйте время на проектирование API будущей системы.

4 Создание нового подхода к управлению инфраструктурой

Микросервисы предъявляют новые требования к инфраструктуре. Не получится взять инфраструктуру монолита и на ней развернуть микросервисы. Нужно учесть множество особенностей и применить специальные инструменты, чтобы не попасть в ситуацию, когда вместо монолита вы создали микросервисный монолит:

Что нужно учесть в оценке:

  1. Создание инфраструктуры для управления API: анализ вызовов, система прав, публикация API и т.д. Для примера рекомендую посмотреть функциональность Apigee.

  2. Переход DevOps-инженеров на работу только в концепции IaC и контейнеризацию.

  3. Реализовать тотальное логирование и мониторинг микросервисной архитектуры.

5 Измерение и проверка SLA каждого микросервиса

Обычно внутри монолита не замеряются SLA вызова функций. Мало кто отслеживает скорость ответа метода в коде или скорость работы хранимки. При разделении монолита на микросервисы, метод, который раньше вызывался из кода, становится вызовом API. Приходится гарантировать другим микросервисам конкретный SLA, чтобы вся конструкция работала предсказуемо.

Для любителей SRE уточню, что здесь было бы правильнее использовать термин SLO, потому что SLA = SLO + санкции за нарушение договоренностей.

Другими словами, ранее неявный SLA становятся явными и требует проработки:

Работа по определению SLA каждого микросервиса, описанию SLA, тестированию и постоянному мониторингу стоит денег, она не случится сама собой. Это довольно сложный процесс и его надо закладывать в бюджет.

6 Микросервисы добавят на порядок больше точек отказа

Вместе со значительным увеличением числа сервисов по сравнению с монолитом, вы получаете рост точек интеграции, усложнение процесса CI/CD и распределение мастер-данных, что значительно усложнит всю инфраструктуру. Шанс получить проблему на проде будет очень высоким, если целенаправлено не вкладываться в fault tolerance на всех уровнях: проектирование архитектуры, разработка и тестирование.

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

  1. Нагрузочное и стресс-тестирование, и, в идеале, применение chaos engineering.

  2. Применение шаблонов проектирования, таких как Circuit Breaker и Tolerant Reader.

  3. Настройка инфраструктуры: service discovery, health-check,...

7 Реорганизация команд

Когда монолит распадется на много маленьких независимых микро-систем, то встанет вопрос, как теперь организоваться людей вокруг этого "роя"?

Общее решение звучит так: создавайте кросс-функциональные команды (build-and-run team) под каждый микросервис. Но есть нюансы. До старта работ обсудите и выберете какая оргструктура подойдет под ваши задачи и ваш бизнес. Обратите внимание на следующее:

  1. Выберите подход к распределению ответственности команд между микросервисами. Например, возьмите вот такой Service per team.

  2. Примерьте на себя InnerSource, чтобы разгрузить команды микросервисов от входящих запросов. InnerSource и микросервисы хорошо работаю вместе.

  3. Выберите стратегию работы с исходным кодом: монорепа, репозиторий под продукт, репозиторий под микросервис. Если вы решите делать не монорепу, то сразу подумайте, как вы будете выносить общий код микросервисов и как будете управлять общими пакетами. Если вы выберите монорепу, то попробуйте найти инструменты для разработки и деплоя, которые смогут поддерживать этот подход.

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

Ремарка о постепенности перехода

Большие системы, на которых бизнес зарабатывает деньги, обычно не переключается одномоментно на новую версию. Типовой график постепенной замены монолита на микросервисы выглядит так:

Самое важно на схеме то, что системы долгое время живут вместе. Даже функциональность, которая уже реализована на микросервисах, не сразу отключается в монолите. Это важно для следующих трех факторов.

8 Обратная совместимость с монолитом

Бизнесу захочется снизить свои риски и не выключать монолит сразу, а переходить на микросервисы постепенно. Функциональность, реализованная в микросервисах, будет работать параллельно с той же функциональностью в монолите. Поэтому вам придется реализовывать обратную совместимость микросервисов с монолитом. Это первая часть работы, которую нужно закладывать в оценку.

Вторая часть работы связана с тем, что монолит не всегда готов принимать потоки данных в протоколах и форматах удобных для микросервисов. Например, монолит работает с SOAP, а вы всё реализовываете на protobuf, или монолит знает WCF, а вы пишите на .NET Core, где WCF реализован частично. Поэтому часто приходится доделывать функции в монолите, чтобы микросервисы могли отсылать в него данные. Чтобы эти задачи были сделаны, нужно заранее договориться с командой монолита с каким приоритетом и по какому процессу они будут принимать задачи от команды микросервисов.

В оценке вам нужно учесть доработки в микросервисах и в монолите для создания обратной совместимости, а также совместное тестирование.

9 Интеграция и обучение служб поддержки

Если система критична для бизнеса, значит у нее уже есть процесс техподдержки. Вам нужно будет интегрироваться со службой техподдержки и выстроить процесс техподдержки двух систем одновременно.

Это обычные действия при замене старой системы на новую. Но что бывает неожиданно, так это то, что раньше техподдержка иногда залезала в базу данных или правила файлик или "пропихивала" что-то вручную по процессу. А теперь база данных не одна, их много и они разные. Файлики где-то в облаке, а информация летает через очереди. Поэтому вам нужно заложить в оценку обучение инженеров техподдержки работе в микросервисной архитектуре.

10 Догоняющий поток фич от бизнеса

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

Чтобы догоняющий поток фич от бизнеса не стал для вас сюрпризом, нужно:

  1. Заранее договориться с командой, разрабатывающей монолит о правилах совместной работы.

  2. Договориться с бизнесом о процессе внесения новых фич в период жизни обеих систем.

В оценке перехода на микросервисы учитывайте координацию команд новой и старой систем по работе над новыми фичами и работы по сохранению обратной совместимости при изменениях в монолите и микросервисах.

Чеклист

По опыту скажу, что эти десять пунктов могут отнять больше времени и денег, чем само написание системы на микросервисах. Перед стартом работы над дроблением монолита на микросервисы рекомендую пройтись по чеклисту, чтобы ничего не упустить:

  1. Мастер-данные

  2. Написание кода по-новому

  3. Проектирование IT-продукта заново

  4. Создание новой инфраструктуры

  5. Измерение и проверка SLA

  6. Вклад в fault tolerance на всех уровнях

  7. Реорганизация команд

  8. Работы по обратной совместимости

  9. Интеграция служб поддержки

  10. Догоняющий поток фич

Если в плане перехода вы учли все пункты, то скорее всего довольно точно попадете в оценку.

После всего описанного выше вы могли задуматься, зачем вообще переходить на микросервисы, если это так долго и дорого? Ответ на этот вопрос есть, например, в моем выступлении на AgileDays 2017 и в описании на microservices.io. Чтобы принять взвешенное решение о переходе, а не просто пойти за модой, желательно оценить плюсы и минусы для вашей конкретной ситуации.


Ссылки для погружения:

  1. The Death of Microservice Madness in 2018, Dave Kerr

  2. The hidden costs of microservices, Wayne Geils, Mike Hostetler

  3. Microservice Trade-Offs, Martin Fowler

  4. Pattern: Microservice Architecture, Chris Richardson

  5. The Hidden Costs of Microservices, Justin Leitgeb

  6. Challenges and benefits of the microservice architectural style Part 1 + Part 2, Andr Fachat

Подробнее..

От монолита к микросервисам ускорили банковские релизы в 15 раз

24.07.2020 12:09:40 | Автор: admin
Бывает, что компания использует устаревшую монолитную IT-систему, с которой сложно быстро выпускать обновления и решать свои бизнес-задачи. Как правило, рано или поздно владелец продукта начинает проектировать новое, более гибкое архитектурное решение.

Недавно мы писали о том, как работают IT-архитекторы, а теперь расскажем подробности об одном из наших кейсов и покажем схему работы системы. В этом проекте мы помогли заменить коробочное банковское приложение на микросервисное ДБО, при этом наладив быстрый выпуск релизов в среднем 1 раз в неделю.



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

Проблемы коробочного монолита


Среди средних и малых компаний востребованы готовые IT-решения, которые можно кастомизировать и выпустить со своим логотипом. Минусы функции приложений из коробки бывают ограничены, а обновления зачастую приходится вносить долго и исключительно через вендора.

Именно такую коробочную систему дистанционного банковского обслуживания (ДБО) использовал один из наших клиентов. Онлайн-банк представлял собой монолитное приложение с достаточно небольшим набором функций.

Для того, чтобы не уступать конкурентам, банку нужно было постоянно внедрять улучшения и новые фичи. Однако, даже для того, чтобы просто передвинуть кнопки в приложении, приходилось обращаться к вендору. Обновления выходили в среднем 1 раз в квартал.

Таким образом, развивать продукт было сложно из-за ряда ограничений:

  1. Вендор вносил желаемые изменения неприемлемо долго, а переписать мобильный интерфейс в конкретной коробке и вовсе было практически невозможно.
  2. Из-за сбоев в шине данных или коробке пользователи зачастую не могли войти в онлайн-банк.
  3. Работать с приложением пользователи могли только в том случае, если у них была установлена самая свежая версия.
  4. Для распределения нагрузки инстансы монолита были развернуты на нескольких серверах, каждый из которых обслуживал свою группу абонентов. При падении одного из серверов пропадал доступ у всех абонентов соответствующей группы.
  5. Вся экспертиза хранилась у производителя коробочного решения, а не в банке.
  6. Из-за того, что банк не мог оперативно внести изменения по просьбам пользователей, а функциональность была недостаточной по сравнению с конкурентами, появился риск оттока клиентов.

В результате банк принял решение постепенно отказаться от коробки и разработать собственное ДБО, с микросервисной архитектурой, чтобы ускорить разработку функций и обеспечить удобство и безопасность для пользователей.

С чего мы начинали


Создание онлайн-банка началось с проектирования верхнеуровневой архитектуры, найма разработчиков в штат и подключения нашей выделенной команды. При этом архитектуру нужно было заложить с запасом прочности, в расчете на будущее расширение.

На старте наша команда Backend-разработчиков занималась реализацией отдельных базовых функций: например, денежными переводами. Однако, у нас был достаточно большой опыт работы с онлайн-банками, один из наших проектов к этому моменту вошел в отраслевой рейтинг Markswebb, поэтому мы предложили банку помощь в проектировании архитектуры и получили зеленый свет.

Архитектура

Вместе с владельцем продукта мы приняли решение использовать Spring Cloud, который предоставляет все необходимые функции для реализации микросервисной архитектуры: это и Service discovery Eureka, Api Gateway Zuul, Config server и многое другое. В качестве системы контейнеров для Docker-образов выбрали OpenShift, потому что инфраструктура банка была заточена под этот инструмент.

Также мы проанализировали, какие особенности старой коробки могут осложнять работу пользователей. Один из основных недостатков заключался в том, что система синхронно работала через шину данных, и каждое действие пользователей вызывало обращение к шине. Из-за больших нагрузок часто происходил отказ шины, при этом переставало работать все приложение. Кроме того, как и во многих старых банковских продуктах, накопилось легаси наследство в виде старого и тяжеловесного CORE АБС, переписывать которое было бы сложно и дорого.

Мы предложили ряд улучшений:

  • Версионирование

Ранее коробка поддерживала только одну версию, а в новом онлайн-банке мы предложили новую архитектуру, которая позволит поддерживать несколько различных версий одновременно и заменять их при необходимости.

Схема версионирования следующая: если минорная версия в сервисе изменилась, то сервис автоматически пересобирается и деплоится, заменяя устаревшую версию. Если мы ставим мажорную версию, то разворачивается новая копия сервиса с новой версией. Таким образом, разработка новых функций с изменением API сервиса не влияет на мобильное приложение, при этом сокращаются сроки тестирования. Такая система позволила обеспечить поддержку даже устаревших версий мобильного приложения, если у пользователя нет возможности обновиться.

  • Асинхронность

Мы реализовали библиотеку, которую можно использовать в сервисах, где требуется асинхронная работа. Библиотека реализует выполнение асинхронных задач, подходит для использования на любом количестве копий сервисов, и они не мешают друг другу. Синхронизация между различными копиями производится с помощью очереди сообщений Kafka.

Это решение помогло повысить стабильность работы приложения. Мобильное приложение теперь не зависит от шины, необходимые пользователю данные мы дублируем в наших сервисах и обновляем их в фоне, когда есть доступ к банковской шине. Все действия пользователя ставятся в очередь на исполнение, по мере готовности приходят PUSH-уведомления о результатах.

  • Кэширование

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

Что изменилось в системе


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





В новом решении использована микросервисная архитектура, что позволяет разворачивать столько копий сервисов, сколько требуется для того или иного функционала. Мы добавили кэширование данных на основе KeyDB, чтобы не только увеличить скорость получения информации, но и снизить нагрузку на базу данных.



Давайте рассмотрим пример получения данных по счетам пользователя в новой архитектуре. Запрос пользователя из мобильного приложения попадает через балансировщик на Gateway, который понимает, на какой из сервисов направить запрос. Далее попадаем на API сервис счетов. Сервис сперва проверяет, есть ли актуальные данные пользователя в Cache. При успешном исходе возвращает данные, в ином случае отправляет запрос в Middle сервис счетов.

Обновление данных в сервисе может происходить в различных случаях. Например, при непосредственном запросе от пользователя сервис создает задачу на обновление данных, которая выполняется асинхронно, и полученные из ESB данные обновляются. Также сервис получает сообщения из очереди сообщений и реагирует на них. Например, сервис получает сообщение о входе пользователя в приложение и сразу же обновляет данные по счетам, получает данные об операциях со счетом от других сервисов и обновляет у себя данные. Таким образом, пользователь всегда видит актуальные данные по своим счетам.

Среди наиболее важных изменений можно отметить следующие:

  • Гибкость масштабирования

Для увеличения отказоустойчивости системы сервисы распределены по разным серверам. Это позволяет сохранять систему в работоспособном состоянии в случае падения одного из них. Для своевременного реагирования на нестандартные ситуации мы внедрили систему мониторинга, это помогло при необходимости вовремя масштабировать сервисы. Подключили DevOps для настройки с нуля CI/CD на серверах клиента, выстроили процессы развертывания и поддержки будущего приложения на нескольких серверах.

  • Ускорение релизов за счет версионирования

Ранее при обновлении мобильной версии одни пользователи уже применяли новую версию, а другие нет, но число последних было минимально. При разработке нового ДБО мы реализовали версионирование и возможность выпускать релизы без риска, что приложение перестанет работать у большой части клиентов. Сейчас при реализации отдельных функциональностей в новых версиях мы не ломаем старые версии, а значит, нет необходимости проводить регресс. Это помогло ускорить частоту релизов минимум в 15 раз теперь релизы выходят в среднем 1 раз в неделю. Команды Backend и Mobile могут одновременно и независимо работать над новыми функциональностями.

Подводя итоги


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

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

Архитектура приложения заложена с учетом дальнейшего роста продукта и инструментов разработки, которые использует банковская инхаус-команда, чтобы владелец продукта мог самостоятельно вносить любые доработки в ДБО. Сроки активной разработки альфа-версии составили около года, еще через 3 месяца вышла бета-версия для всех пользователей.
Надеемся, что описанная схема работы может быть полезна при создании других финтех-продуктов.

Спасибо за внимание!
Подробнее..

Выбор архитектурного стиля (часть 1)

28.08.2020 14:05:29 | Автор: admin
Привет, хабр. Прямо сейчас в OTUS открыт набор на новый поток курса Software Architect. В преддверии старта курса хочу поделиться с вами своей авторской статьёй.



Введение


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

Немного истории


Если вы попробуете задать вопрос разработчикам: Зачем нужны микросервисы?, то вы получите самые различные ответы. Вы услышите, что микросервисы улучшают масштабирование, упрощают понимание кода, улучшают отказоустойчивость, иногда можно услышать, что они позволяют очистить код. Давайте обратимся к истории, чтобы понять, какую цель приследовало появление микросервисов.

Если говорить вкратце, то микросервисы в нашем текущем понимании возникли следующим образом: в 2011 Джеймс Льюис, анализируя работы различных компаний, обратил внимание на появление нового паттерна micro-app, который оптимизировал SOA с точки зрения ускорения развертывания сервисов. Несколько позже, в 2012 году, на архитектурном саммите паттерн был переименован в микросервис. Таким образом, первоначальной целью внедрения микросервисов было улучшение пресловутого time to market.

На волне хайпа микросервисы были в 2015 году. По некоторым исследованиям, ни одна конференция не обходилась без доклада на тему микросервисов. Более того, некоторые конференции были посвящены исключительно микросервисам. Сейчас же очень многие проекты начинаются с применением данного архитектурного стиля, а если проект содержит тонны legacy-кода, то наверняка активно осуществляется миграция на микросервисы.

Несмотря на все вышесказанное, до сих достаточно небольшое количество разработчиков может определить понятие микросервис. Но об этом мы поговорим несколько позже

Монолит


Архитектурным стилем, противопоставляемом микросервисному, является монолит (или все в одном). Что такое монолит рассказывать, наверное, не имеет смысла, поэтому я сразу перечислю недостатки этого архитектурного стиля, которые инициировали дальнейшее развитие архитектурных стилей: размер, связанность, развертывание, масштабируемость, надежность и косность. Ниже я предлагаю озномится с каждым из недостатков отдельно.

Размер


Монолит очень большой. И общается он как правило с очень большой базой данных. Приложение становится слишком большим, чтобы его мог понять один разработчик в принципе. С монолитом хорошо работать могут только те, кто провел за этим кодом достаточно много времени, тогда как новички потратят очень много времени на попытки разобраться с монолитом и не факт, что разберутся. Обычно при работе с монолитом всегда есть некоторый условный senior, который знает монолит более-менее хорошо и бьет по рукам в течении года-полутора других новых разработчиков. Естественно, что такой условный senior является единой точкой отказа, и его уход может привести к гибели монолита.

Связанность


Монолит представляет из себя большой комок грязи (big ball of mud), изменения в котором могут привести к непредсказуемым последствиям. Внося изменения в одном месте, можно повредить монолит в другом (то самое ухо почесал, *@ отвалилась). Связано это с тем, что компоненты в монолите имеют очень сложные и, главное, неочевидные взаимосвязи.

Развертывание


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

Масштабируемость


Модули монолита могут иметь конфликтующие потребности в ресурсах, из-за чего необходимо искать компромисс с точки зрения железа. Представьте себе, что у вас монолит состоит из сервисов A и B. Сервис A требователен к размеру жесткого диска, а сервис B к оперативной памяти. В таком случае, либо машина, на которую ставится монолит, должна поддерживать требования обоих сервисов, либо придется руками, искуственно один из сервисов отключать.

Еще один пример (более классический): сервис A намного более популярен, чем сервис B, поэтому вы хотите, чтобы сервисов A было 100, а сервисов B было 10. Опять-таки два варианта: либо разворачиваем 100 полноценных монолитов, либо на каких-то из них руками сервисы B придется отключать.

Надежность


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

Косность


Ввиду размера монолита тяжело перейти на новые технологии. Как следствие, отдельной задачей вырисовывает удержание того самого условного senior'а. Выбранный на старте проекта технологический стек может стать блоком, препятствующим развитию продукта.

Заключение


В следующий раз мы поговорим о том, как люди попытались решить обозначенные проблемы, перейдя к компонентам и SOA.



Читать ещё:


Подробнее..

Ускоряем доставку изменений в классический windows-монолит

16.12.2020 16:22:14 | Автор: admin
Добрый день, коллеги! Позвольте представиться меня зовут Павел Бацев, я администратор сервисов в ГК Спортмастер. В системном администрирование 8 лет, второй год занимаюсь изучением и внедрением devops-практик.

Сегодня я предлагаю рассмотреть вам кейс, который, прежде всего, будет интересен администраторам и инженерам с парком windows-хостов и монолитными системами.

Под катом: некоторые особенности работы конвейера доставки, работающего с использованием windows-агентов bamboo; проблемы, возникающие при использовании dsc и jea-сессий powershell в домене с устаревшим уровнем леса, и варианты их решения; способ внедрения автоматического ui-тестирования без задействования профессиональных тестировщиков.

Итак, рассмотрим, исходные данные:

Имеем бизнес-критичную информационную систему, которая интегрирована с системой внутреннего документооборота, системой заявок в Службу горячей линии, 1С.

На момент получения системы в поддержку у нас не было стратегии по релизам, поэтому все операции, связанные с обновлением той или иной компоненты, выполнялись в мануальном режиме, зоны ответственности были размазаны, не было организовано четкой, взаимодополняющей работы между командами разработки, администрирования и аналитики (как представителя бизнеса).

Система, о которой идет речь, имеет классическую монолитную архитектуру и состоит из:

  • Базы данных MS SQL;
  • Веб-сервера IIS;
  • Веб-сервиса IIS;
  • Шедуллера регламентных заданий Служба Windows;
  • Кеша Redis, как служба Windows.


Как вы понимаете, это система, в которой полная потеря функциональности может возникнуть при выходе из строя любого из компонентов. Что сильно усложняет гибкость в подходе и частоте доставки изменений.

Исходя из рутинных задач были определены операции, которые требуют автоматизации и выполнение в рамках единого конвейера, а также учтён задел на последующие развитие:

  • Доставка сборок (сформированных артефактов) на целевые хосты веб-серверов;
  • Кастомизация сборок правкой файлов контента, параметров верстки, адресов сторонних плагинов и прочее.
  • Выполнение скриптов миграций утилитой (набором bat/ps-скриптов) от разработчика, находящейся в теле сборки;
  • Организация верной последовательности запуска системы;
  • Лёгкий откат при возникновении неполадок конвейера и ошибках кода.
  • Масштабируемость выполнения (при росте агентов bamboo, росте количества целевых контуров/хостов и т.п.) и унификация для различных контуров (dev, test, stage, prod);
  • Использование вычислительных мощностей агентов bamboo;
  • Вывод полного и читабельного лога выполнения всех шагов в ui bamboo;
  • Организация возможности выполнения конвейера и первичной диагностики возникающих проблем командой аналитики, а не техническим экспертом или т.п.
  • Реализация системы оповещения о результатах выполнения конвейера в удобный бизнесу инструмент: выбор пал на канал telegram (простейшая реализация chatops).


В нашей компании реализованы различные инструменты, позволяющие внедрять практики devops. На момент моего вступления в должность администратора сервисов наиболее развитым и способным покрыть поставленные задачи был стек от Atlassian, поэтому реализацию конвейера было решено выполнять, используя связку jira+bitbucket+bamboo.

Так как обслуживаемая система использует ОС Windows Server, а имеющийся на тот момент пул bamboo-агентов был на *nix, возникла идея проверки работы кроссплатформенного взаимодействия. Всё было хорошо, powershell core, установленный на *nix-агенты, работал исправно, но при тестировании сетевого взаимодействия выяснилась проблема не отрабатывали второй тап аутентификации между windows-хостами.

Какие варианты решения были рассмотрены


Попробовали мы вот что.

  • установка библиотеки Kerberos и работа по аналогии с Ansible for Windows;
  • использование Python PowerShell Remoting Protocol Client library и зависимых с ним пакетов;
  • использование windows агентов bamboo.

После обсуждения с коллегами предложенных вариантов мы решились на внедрение некоторого количества агентов bamboo на windows, что позволило унифицировать платформу агента и целевой системы, отказаться от длительной исследовательской деятельности, а также обезопасило от возможных проявлений неявных проблем при кроссплатформенной работе инструментов ci/cd.

Не обошлось без сложностей и при реализации конвейера доставки изменений на базе windows агентов bamboo, куда же без проблем. Собственно, вот они:

  • текущий лес ad не поддерживает групповые управляемые учетные записи служб (gMSA);
  • при использовании встроенного плагина bamboo по обработке скриптов Script и хранении скриптов в СКВ, при получении ошибок powershell встроенные интерпретатор bamboo не воспринимал их и завершал задачи\задания\шаги\планы, как удачные;
  • сторонний плагин Parse Log Task для простейшего парсинга ошибок по заданным паттернам было невозможно добавить в задачи Deployment Projects.

Реализованный конвейер


Остановимся на общей концепции, инструментах и некоторых особенностях.

Система контроля версий


В качестве СКВ используется bitbucket, но так как используется ПО с закрытым исходным кодом, то в СКВ хранится только обвес (скрипты и конфиги) для нормальной работы конвейера. Хранение скриптов конвейера организовано в рамках одного репозитория, разделение контуров\типа конвейера идёт по бранчам. Структура папок для всех бранчей унифицирована.



CI/CD


Реализация всех процессов CI/CD сведена в выполнение билд-плана bamboo по причинам, выявленным в процессе разработки концепта, и наличия некоторых недостатков инструментария от Atlassian.



Все шаги унифицированы и представляют собой задание, разделенное на несколько простых задач. Разберем на примере шага Build.

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

Да, отмечу, что при реализации всех шагов конвейера используется инструментарий powershell. В частности dsc и jea. А раз была проблема с использованием gMSA, то мы разработали концепцию с задействованием временных шар, срок жизни которых ограничен временем выполнения задания конвейера. Отсюда появляются задачи с характерным признаком TFP и DelShare:

  • создание временной области на текущем агенте:
  • удаление временной области на текущем агенте.


В итоге вроде бы простейшее задание разбивается на семь задач:

  1. получение кода скриптов на агент bamboo;
  2. создание временной области, для хранения dsc;
  3. парсер результата задачи создания временной области;
  4. выполнение основной смысловой задачи шага;
  5. парсер результата выполнение основной задачи;
  6. удаление временной области;
  7. парсер результата задачи удаление временной области.


В рамках билд-плана создали зависимость выполнения другого билд-плана для реализации оповещений в telegram.





Этот конвейер является базовым и разделен на бранч-планы поконтурно для минимизации количества отдельных идентичных планов. В дальнейших конвейерах мы доработали паттерны ошибок, именование тестов, доработали/переработали скрипты ps и сделали прочие полезные изменения.

Одним из результатов стал конвейер обновления версии платформы для продуктивного контура.

Также реализовали конвейеры, покрывающие другие типовые задачи: обновление сущностей БД, используя утилиту собственной разработки подрядчика или утилиту от redgate; автоматическое ui тестирование системы; обновление\добавление кастомного контента js\css; перезапуск системы непродуктивного контура; оповещения в telegram.

Написали инструкции для группы аналитиков и провели обучающие встречи по использованию инструментов CI/CD.

А ещё разработали концепт и протестировали выполнение конвейеров по переходам бизнес-процесса в jira\отложенному заданию (не востребовано, т.к. заказчик пожелал использовать ui bamboo).

Ближайшие планы


  • перенос хранения сборок с сетевой шары в Artifactory;
  • после обновления леса ad внедрение gMSA;
  • написание своего плагина bamboo для оповещений в telegram;
  • написание своего плагина bamboo для парсинга результатов выполнения ps-скриптов из файла.


Автотестирование без профессиональных тестировщиков


Теперь же про успешно реализованный кейс по разработке и внедрению UI-автотестов с минимальными трудозатратами и квалификацией по инструментарию.

От бизнеса были получены сценарии с описанием бизнес-процессов, критичных к отслеживанию.

В качестве инструментария мы взяли:

  • selenium ide как доступная и удобная платформа для формирования скелета автотеста с возможностью импорта в различные языки программирования;
  • selenium webdriver+node js+mocha как связка кроссплатформенная инструментов, подходящая к текущей конфигурации и набору установленных плагинов в bamboo;
  • windows-агенты bamboo как раннеры тестов;
  • allure как визуализатор результатов для бизнеса, удобный и простой в понимании;
  • канал telegram как простейшая реализация chatops.


В selenium ide были записаны скелеты автотестов по сценариям от бизнеса.



Сценарии были импортированы в js и доработаны для выполнения в рамках выбранного инструментария.

Полученные конечные скрипты для UI-автотестирования были загружены в СКВ и разбиты по контурам.



После успешного завершения конвейер релиза, в зависимости от контура, запускает конвейер UI-тестирования.

По завершении формируется артефакт с детальным логом выполнения.


Все тесты завершены успешно


Все или часть тестов завершены неудачно

Плюс в telegram-канал приходит информация о результате, с детальным логом результатов.


Все тесты завершены успешно


Все или часть тестов завершены неудачно

Затем проведена передача знаний команде аналитиков, которая на основе сформированных скелетов и завершенных скриптов автотестирования самостоятельно выполняет доработку\разработку.

Это дает возможность:

  • исключить лишние шаги по постановке/проверке выполнения заданий между командами администрирования и аналитики;
  • увеличить вовлечённость команд в общий процесс внедрения devops-практик;
  • де-факто организовать прообраз продуктовой команды;
  • ускорить реализацию заданий от бизнеса.


Если вы сталкивались с подобным и используете windows-монолит, поделитесь, пожалуйста, своим опытом доставки изменений.
Подробнее..

Из монолита на микросервисы меняем архитектуру правильно и безболезненно

27.01.2021 10:08:05 | Автор: admin
Как собрать в прямом эфире 17 000 зрителей? Значит, рецепт такой. Берем 15 актуальных IT-направлений, зовем зарубежных спикеров, дарим подарки за активность в чате, и вуа-ля крупнейший в Украине и восточной Европе онлайн-ивент готов. Именно так прошла ежегодная мультитул конференция NIXMultiConf.

Под слоганом айтишникам от айтишников эксперты из Украины, Беларуси, России, Великобритании и Германии поделились опытом и рассказали о новинках индустрии. Полезно было всем дизайнерам, девелоперам, тестировщикам и менеджерам. И теперь делимся инсайтами с вами.

По мотивам докладов экспертов NIX продолжаем серию материал на самые актуальные темы. В новой статье PHP developer Александр Павленко объясняет, на каком этапе разработки стоит перейти на микросервисы и как это сделать с минимальными рисками.

Хочешь знать больше смотри конференцию на YouTube-канале.


Привет! Я Александр Павленко, разработкой на PHP занимаюсь около четырех лет. Среди крупных проектов Car Sales Platform + Inventory, Archive of Scientific Documents, Job Search Platform, Natural Disasters Alarm System.

Стоит только заговорить о монолите и микросервисах, как многие начинают холивар вокруг их сравнения. Я считаю, вместо поиска плюсов и минусов, лучше выяснить, какой подход больше всего отвечает бизнес-задачам приложения. Наша команда занималась проектом в сфере FinTech, и он изначально строился на монолите. Почему так сложилось и какие возможности мы увидели в микросервисах расскажу подробнее.

Стартовать проще с монолитом


Монолит напоминает мне кубик Рубика: если вытащить из него одну деталь, собрать новую форму или добавить другие компоненты, кубик уже не будет полноценно работать. Каждый элемент формирует единый функционал. Если какой-то части не хватает, она сломана или стоит не на месте цветное поле кубика не сложится.

В условиях стартапа с монолитом удается быстрее запустить проект. Когда, условно через месяц, надо презентовать клиенту MVP, но ни конкретных требований, ни спецификаций по продукту нет, спасает только гибкость монолита. Во-вторых, на старте его легко и быстро масштабировать. Для команды тоже были очевидны преимущества. К разработке на монолите может присоединиться больше специалистов, в том числе новички. В изучении PHP они непременно начинают с монолита. Он прост и понятен в использовании.

Наш стартап стремительно развивался. Росло количество пользователей, клиентов, регулярно добавлялся различный функционал. Спустя время проявились недостатки монолита. То, что было критично для нас:

  • из-за стремительного роста системы становилось сложнее ее поддерживать и развивать без дополнительных ресурсов. Прежде всего это касалось стоимости внесения новых изменений. Чем дальше мы шли и внедряли новые фичи, тем больше они дорожали.
  • рисковали в будущем застрять на старых технологиях. Думаю, многие коллеги сталкивались с legacy-монолитами за окном 2020-й год, а на мониторе в коде 2003-й. Переписывать все это крайне сложно. Обычно не хватает ни времени, ни ресурсов.

К счастью, мы заранее предвидели риски, поэтому переход на новую архитектуру не шокировал. Все прошло плавно и спокойно. Микросервисный подход решил несколько задач:

  • многократное использование микросервисов позволяло легче адаптироваться под новые требования стартапа и масштабировать его;
  • внедрять новый функционал без дополнительных затрат;
  • упрощать интеграцию последующих приложений;
  • использовать разные языки программирования под микросервисы и разные виды протоколов для общения между ними.

Но тут же вспылили недостатки. Во-первых, повысился порог вхождения в проект. Во-вторых, усложнилось поддержание, конфигурация и тестирование настроек. По сути это не является минусом. Главное, что у нас микросервисами закрыли самые важные вопросы.

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

Микросервисы хороши и тем, что их можно развертывать и тестировать независимо друг от друга. Это упрощает жизнь команде как в процессе разработки, так и в дальнейшем развитии проекта.

Что микросервисы дали нашему проекту:

  • взаимодействие PHP и Golang. Отлично дополняют и в некоторых случаях перекрывают слабые стороны друг друга. По сравнению с PHP, с помощью Golang можно значительно улучшить перфоманс. За счет параллелизма ускорить обработку и выполнение тех или иных процессов. В тоже время у PHP есть все для быстрой реализации удобного CRUD;
  • от пяти крупных клиентов мы перешли к более чем 20-ти все благодаря разграничению монолита на отдельные решения;
  • оптимизировали нагрузку на сервера. По сравнению с PHP, Golang потребляет намного меньше памяти. С его внедрением и переписыванием и развитием нескольких частей приложения на Golang серверам стало легче. Больше мы с этой проблемой не сталкиваемся;
  • разнообразили команду. Переход к микросервисам это не только изменение архитектуры кода, но и самой команды. Мы поделились по зонам ответственности. Когда-то нас было пятеро, сейчас около 40 человек. Добавились бэкенд-разработчики и бизнес-аналитики, заточенные под определенные спецификации.

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

Не обошлось без сложностей для новых членов команды. Им нужно больше времени, чтобы понять, как микросервисы между собой взаимодействуют и делают ли это вообще. Насколько глубоко начинающий разработчик должен в этом разбираться? Чем разнообразнее база знаний, тем специалист ценнее на рынке и может оперативно реагировать на изменения в проекте. Когда есть, с чем сравнивать, намного легче среди нескольких вариантов выбрать наиболее подходящий в текущий момент. Поэтому, как минимум, ознакомиться с этим архитектурным подходом я советую всем. Новичок может начать с более простых вещей с монолита но помнить, что когда-нибудь придется углубиться в микросервисы. Все-таки тренды индустрии никто не отменял.

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

Получается, микросервисы рулят?


На самом деле, окончательного ответа нет. В тех или иных ситуациях бывает логичнее стартовать с монолита. Но в будущем система может достичь таких масштабов, что переход к микросервисам неизбежен. Из личного опыта я отметил пару сценариев, в которых стоит задуматься о переходе на микросервисы:

  • когда в монолитном проекте стоимость нового функционала не перекрывает ожидаемую пользу;
  • когда проект разрастается до такой глыбы, что новые люди в команде теряются. В микросервисах можно взять отдельный компонент, определить, что в нем происходит и работать только с ним. В крупных проектах разделение обязанностей рано или поздно приведет к архитектурным разграничениям. Микросервисы позволяют легче пережить этот момент.

Иногда мы сталкиваемся с настойчивыми клиентами, которые отказываются от здравой идеи разработчиков. Вот вздумалось ему только эту технологию или архитектуру применять. Почему? Да потому что. Слышал в интернете или Все так делают. Заказчик редко задумывается о подводных камнях, на которые могут наткнуться программисты. Если вы видите, что есть более эффективный подход, идея заказчика вызовет новые проблемы или вообще остановит развитие проекта, ваша задача не бояться сказать клиенту, что он не прав. Объясните, почему лучше использовать ту или иную технологию или подход. Как показывает практика, когда вы можете аргументировать преимущества своей идеи и недостатки предложенного заказчиком решения, он спокойно примет вашу сторону. Проект это его детище, его деньги, и прежде всего клиент заинтересован в эффективности и прибыльности продукта.

В нашем случае мы разработали много спецификаций, которые жили обособленно и полноценно не взаимодействовали друг с другом. А как только разбили их на независимые микросервисы, получили высокие показатели в перформансе и счастливого заказчика, который приумножил прибыль. Подробности можно узнать из моего доклада на NIXMultiConf.
Подробнее..

Перевод Как Asana использует Kubernetes

03.05.2021 06:23:19 | Автор: admin

image


В Asana мы используем Kubernetes для развертывания сервисов и управления ими независимо от монолитной инфраструктуры. Поначалу у нас были некоторые проблемы, и чтобы стандартизировать создание и обслуживание приложений Kubernetes, мы создали фреймворк с незамысловатым названием KubeApps. В последние два года наша команда по инфраструктурной платформе вносила улучшения в KubeApps, чтобы упростить развертывание сервисов в Asana. Здесь мы расскажем, какие проблемы мы хотели решить в Kubernetes и как мы это сделали с помощью фреймворка KubeApp.


Введение


Мы уже рассказывали о legacy-системе деплоймента в Asana наша основная инфраструктура организована как монолит инстансов AWS EC2 с кастомными скриптами конфигурации для каждого сервиса. Никакого масштабирования у нас не было: отправляешь новый код в монолит переконфигурируй все хосты. Чтобы добавить новый сервис, нужен был новый набор кастомных скриптов конфигурации. Все это было сложно обслуживать, плюс был риск увеличить нестабильность деплоев в монолите.


Когда мы обдумывали инфраструктуру для Luna2, решили использовать Kubernetes, чтобы деплоить сервисы и управлять ими независимо от монолита. Оркестрация контейнеров пошла хорошо, и остальные инженеры захотели использовать Kubernetes для других систем Asana. Мы доработали эти инструменты, чтобы и другие команды могли собирать и деплоить сервисы в контейнерах.


Kubernetes в Asana


С Kubernetes управлять сервисами стало гораздо проще, ведь у нас есть четкие границы между процессами и окружениями, где они выполняются. В итоге разработчики приложений могут собирать и обновлять одни сервисы, не боясь навредить другим.


Расширять инфраструктуру за пределы монолита EC2 стало, конечно, проще, но Kubernetes пока не решал всех наших проблем (примечание: В Kubernetes есть Cloud Controller Manager, который управляет нодами, настраивает маршруты между контейнерами и интегрируется с компонентами облачной инфраструктуры).


  • Управление ресурсами AWS никак не связано с Kubernetes. Разработчикам надо было заранее создавать ASG и готовить их для контейнеров Docker и любых других ресурсов, которые могут понадобиться приложению.
  • Мы тратили слишком много времени на инструментирование во всех сервисах, например, для сборки метрик и настройки разрешений для секретов, причем мы постоянно делали одно и то же настраивали ELB, управляли группами конфигурации для каждого приложения...
  • Continuous delivery в Kubernetes не встроена. На уровне абстракции Kubernetes логика приложения должна быть упакована в образы, доступные в container registry.

Чтобы решить эти проблемы и стандартизировать создание и обслуживание приложений Kubernetes, мы создали фреймворк с незамысловатым названием KubeApps. Изначально мы задумали KubeApp для обработки всех аспектов развертывания от сборки необходимых ресурсов до обновления DNS во время деплоя и плавного перехода между версиями кода. Каждый KubeApp определяется набором требований к железу, определений подов и спецификаций сервиса.


Конфигурация как код


Все конфигурации KubeApp существуют в виде Python-кода, поэтому поддерживают программно созданные конфигурации и обеспечивают согласованность с помощью общих библиотек. С этими конфигурациями мы можем объявлять и настраивать внешние ресурсы, необходимые для KubeApp.


На схеме показаны спецификации примера веб-приложения и способ его представления в системе конфигурации KubeApp. Деплоймент запрашивает оборудование, ELB и сборки образов. Мы предоставляем дефолтные спецификации для обработки конфигураций DNS и включаем определения подов для обработки метрик и логирования.



Образы Docker с continuous deployment


Код приложения пакуется в Docker-образы с помощью образов Bazel или традиционных Dockerfile. Наш KubeApps собирает и отправляет эти образы в рамках пайплайна CD, так что образы для любого сервиса доступны в нашем registry.


Для сборки зависимостей и управления ими в большинстве случаев мы используем Bazel. Это особенно удобно с контейнеризованными приложениями, потому что таким образом мы объявляем зависимости и упаковываем сторонние библиотеки в исполняемые файлы. Так мы получаем детерминированные выходные данные при настройке контейнерных окружений для каждого приложения.


По одному кластеру на KubeApp


При использовании Kubernetes нужно решить, как делить сервисы между кластерами (примечание: некоторые соображения о компромиссах при выборе числа кластеров приводятся в этой статье на learnk8s.io: Проектирование кластеров Kubernetes: сколько их должно быть?). Деплоить сервисы в один кластер Kubernetes это экономично и удобно в плане администрирования, потому что сервисы используют одни ресурсы мастер-ноды, а такие операции, как апгрейд версий Kubernetes и деплойменты, нужно выполнять всего один раз. Но модель с одним кластером не особо хороша для мультитенантности, а кластер становится единой точкой отказа. Один кластер Kubernetes ограничен в плане масштабирования, так что при достижении определенного размера неплохо было бы его разделить.


В Asana каждый KubeApp деплоится в своем кластере Kubernetes через AWS EKS. Такой подход гарантирует безопасность и устойчивость приложения. Каждый кластер отвечает за один сервис, так что можно не волноваться о состязании за ресурсы между сервисами, а если кластер упадет, пострадает всего один сервис.


Управлять несколькими кластерами сложновато, потому что дефолтные инструменты Kubernetes могут взаимодействовать только с одним кластером за раз. Поэтому мы создали инструменты для управления несколькими кластерами одновременно в KubeApps. Еще мы обнаружили, что такая модель позволяет владельцам отдельных KubeApp независимо управлять кластером (апгрейдить ноды, масштабировать деплои и т. д.)


Процесс развертывания KubeApp


image


Для развертываний KubeApp мы используем центральный хаб управления, который мы назвали kubecontrol. Его можно настроить для обновления вручную или автоматически, через cron. Развертывание KubeApp включает несколько шагов:


  1. Для обновления или создания KubeApp мы вводим команды в kubecontrol.
  2. Из спецификаций приложения мы запрашиваем набор ресурсов, необходимых для KubeApp (Auto Scaling Groups, спотовые инстансы и т. д.). Создается новый кластер EKS.
  3. Мы делаем запрос к сервису сборки образов, чтобы собрать образ docker с определенной версией кода. Сборщик образов компилирует код для KubeApp и отправляет образ в ECR (Elastic Container Registry), если его там еще нет.
  4. После сборки всех ресурсов мы передаем спецификации компонентов кластеру Kubernetes, чтобы он получил нужные контейнеры docker от ECR и задеплоил их на нодах.

Полное обновление KubeApps это blue-green деплой, для которого нужно запустить и настроить новый кластер EKS в AWS. Убедившись, что новый KubeApp работает, мы переключаем нагрузку на новый кластер и сносим старый. В KubeApps можно делать rolling апдейт, при котором обновляются образы на запущенном кластере. Это позволяет быстро и незаметно переходить с одной версии кода на другую без запуска целого нового кластера.


Консоль управления KubeApp


До недавнего времени единственным способом прямого мониторинга или управления KubeApp было ssh-подключение к kubecontrol и взаимодействие с приложением через CLI. Искать информацию о деплоях было непросто, так что пользователям приходилось изучать логи, чтобы понять, когда в KubeApp была развернута определенная версия кода. Чтобы внести больше ясности, мы создали KubeApp Management Console (KMC), которая отвечает за запись информации о прошлых деплоях. Мы хотим использовать эту консоль как централизованный веб-интерфейс, в котором пользователи могут взаимодействовать с KubeApps.


Что собой представляет KubeApps сегодня и что будет дальше


Сейчас у нас больше 60 KubeApp в Asana, которые поддерживают самые разные рабочие нагрузки от управления релизами до распределенного кэширования. Пока мы сохраняем монолит инстансов EC2, но уже переделываем эти сервисы в контейнеры в KubeApps.


Команда инфраструктурной платформы продолжает активную работу над KubeApps. В будущем мы планируем поддерживать больше архитектур (ARM64) и провайдеров инфраструктуры (AWS Fargate). Еще мы планируем создать инструменты для более удобной разработки в KubeApps, чтобы их можно было запускать в песочницах и локальных окружениях. Благодаря этим и другим изменениям фреймворк KubeApps можно будет приспособить для любой рабочей нагрузки, которая может нам понадобиться.

Подробнее..

Recovery mode 2.07 онлайн-митап про микросервисы и Unit-тесты

25.06.2020 00:10:20 | Автор: admin
В четверг 2 июля собираемся обсудить очередной опыт распила монолита и рассказать, как Unit-тестирование сокращает время разработки. Старт в 16:00 мск, в 17:00 по Ижевску.

Участие бесплатно, нужна регистрация.

Упрощаем себе жизнь с помощью Unit-тестирования


Юнит-тесты повышают скорость разработки согласны?

  • расскажу, почему нетестируемые проекты увеличивают сроки релизов;
  • приведу аргументы в пользу написания юнит-тестов. Рассмотрим, почему хороший дизайн тестируемый, а обратное неверно;
  • плохие юнит-тесты хуже, чем ничего. Поговорим про требования к юнит-тестам. Например, почему важна изолированность или скорость выполнения тестов;
  • расскажу про лучшие практики юнит-тестирования с примерами на NUnit.


Как отпилить часть монолита и не сойти с ума


Я расскажу о нашем опыте отделения части функциональности сервиса в отдельный микросервис:

  • неправильная оценка задачи и её последствия. Как избежать ситуации, когда задача распухает, сроки переносятся, и все нервничают;
  • что делать и чего не делать с зависимостями при разделении проектов;
  • компромиссы, на которые должен идти разработчик или как перестать искать идеальные решения и начать делать рабочие.


Вход свободный, не забудьте зарегистрироваться, чтобы получить ссылку. Если не хватило вводных welcome в комментарии.

А ещё смотрите там же на сайте анонс митапа по управлению проектами 9 июля.

И приходите, будем рады!
Подробнее..

Микросервисы VS монолит баттл адептов

09.02.2021 10:17:03 | Автор: admin

Монолитная и микросервисная архитектуры два диаметрально разных подхода. Во время круглого стола на конференции DevOps Live 2020 столкнулись адепты этих архитектур, которые в формате баттла искали ответы на самые актуальные вопросы. Избыточны ли ресурсы на каждый микросервис? Есть ли необходимость в постоянном рефакторинге? И как грамотно организовать рабочее место?

Адвокатом микросервисов выступил Алексей Шарапов, а обвинительную речь зачитал Андрей Булов. Оба сотрудники Deutsche Telekom IT Solutions стратегического подразделения крупнейшей в Европе телекоммуникационной компании Deutsche Telekom и не новички в обсуждаемом вопросе.

Андрей Булов: Я работаю в довольно крупном энтерпрайзе, в котором берут свое начало молодые стартапы. Побывал в разных ролях: архитектора, девелопера. С 2016 года начал писать на микросервисах.

С тех пор я невзлюбил паттерн Microservice as a goal, которым грешат многие энтерпрайзы, и стал пропагандировать здравый смысл. Честно говоря, я считаю, что микросервис и текущая разработка это что-то типа Spotify в Agile: все хотят внедрить, но не все понимают, зачем это нужно.

Тема этого мини-баттла родилась чуть ли не из кухонного спора. Я устал всем доказывать, что микросервис это не Грааль, не панацея, и готов поделиться своим мнением.

А еще я люблю лямбды, и считаю, что микросервис это некое переходное звено.

Алексей Шарапов: На данный момент я являюсь DevOps евангелистом. То есть хожу и очень громко всем говорю: Давайте делать DevOps!. Я в разработке с 2010 года. Занимался разработкой фронтенда и немного бэкенда. С 2015 года влюбился в DevOps и DevOps-практики. Стараюсь заниматься ими ежедневно и приносить счастье нашим разработчикам.

Я работаю с Андреем в одной компании. Это крупный энтерпрайз. И у нас есть исключительно микросервисные проекты, которые я полюбил всем сердцем. Поэтому я выступлю адвокатом микросервисов.

Андрей Булов: Начнем с меня. Почему микросервисы это плохо? Во-первых, потому что это очень дорого. Почему-то считается, что у всех, как у Google, есть куча намаринованных маленьких серверов, в которые можно засунуть маленькие сервисы, и все будет прекрасно работать.

На самом деле, вам придется купить облако и Кубер, и во всей этой виртуализации будет работать Docker, в котором зашиты ОС Java-машина, Application Server и микросервис, раздающий три строчки. А вы будете греть воздух всей этой чудесной инфраструктурой.

С точки зрения программной оптимизации, микросервис это постоянная перегонка из строк в строки. Это съедает массу памяти, и возникает нагрузка и на сеть, и на программистов. Микросервисы дорого имплементировать, и не всегда понятно, зачем люди их выбирают.

Тот же монолит или мелкая галька прекрасно выполняются на Bare Metal, не требуют особых ресурсов, Application Server JVM. И внутри себя они общаются по бинарным внутренним протоколам, байтики бегают по серверу: все прекрасно и довольно быстро работает.

Да, можно писать не на JVM, но все равно выходит недешево. Микросервисы обходятся дорого с точки зрения перформанса, скорости разработки и работы внутри.

Алексей Шарапов: На все это могу ответить, как человек, занимающийся инфраструктурой в крупных компаниях последние несколько лет, что мы можем делать очень много классных вещей. В первую очередь, ограничивать минимум. Если на наш сервис нет нагрузки в спокойном состоянии, можем сделать ему минимальные ресурсы. Мы должны содержать Kubernetes-кластер, какие-то дополнительные сущности, но запуском внутренних компонентов можем управлять очень-очень тонко. И если в какой-то момент нам на определенное время нужны сущности, мы можем использовать CronJob. А еще Openfaas, о чем часто забывают. Мы не греем наш кластер ненужными сущностями, а запускаем только то, что необходимо.

Хорошо, когда инженер по инфраструктуре сотрудничает с разработчиками каждый день, подключается к ним ближе и может дать полезные советы, как вынести часть какого-то функционала дополнительно.

Например, можно использовать те же самые AWS лямбды и запускать в них какой-то код да, может быть, это будет не в кластере, а отдельно. Кроме того, не стоит забывать, что у нас есть Kubernetes-кластер. Мы можем не иметь его у себя, а запускать где-то на стороне. Такую возможность предоставляет облачный провайдер.

Не стоит забывать и о том, что когда мы запускаем на Bare Metal, нужно какое-то общее окружение, с которым мы работаем. Если все это учесть, получается даже чуть больше, чем в кластере Kubernetes.

Андрей Булов: Микросервисы это штука, которая требует некоей Java-команды и постепенного обучения. То есть вы девелопите какой-то микросервис, и в нем может постепенно меняться его бизнес-контекст. Многие забывают, что помимо обычного советского рефакторинга, который нужно делать практически каждый день, микросервисы еще требуют бизнес-рефакторинга. Если в монолите вы можете просто порефачить модули и сделать git push force, как тимлид или девелопер, то в микросервисах вам придется договориться с другими командами, с другими людьми и, например, перенести функционал из одного микросервиса в другой.

Мой личный опыт: когда разрастается какой-нибудь важный микросервис типа Order-микросервиса, или Booking-микросервиса, который выполнял 90% функционала приложения, по-моему, немного теряется смысл. Нам требовался временный рефакторинг в заказной разработке или в бизнесе. Довольно трудно продать людям, которые заведуют деньгами, что нам нужно еще пару спринтов, чтобы перекроить бизнес boundaries наших микросервисов. Потому что с первого раза (и со второго, и с третьего) мы не смогли понять этот контекст, зато теперь научились.

Я это лично продавал продуктоунерам. Это занимательно. Если уж вы отважились на микросервисы, всегда помните о том, что рефакторинг не закончится никогда. Он как ремонт, и вам нужно будет всегда со всеми договариваться. Закладывайте хотя бы процентов 20 времени исключительно на это.

Алексей Шарапов: С мыслями о рефакторинге я не согласен. Если API меняется от версии к версии, возможно, это включает в себя несколько проблем, которые больше на совести девелопера, разрабатывающего эту часть. Либо нужно запланировать, что не стоит вводить постоянные изменения, включая новый функционал микросервисов.

С другой стороны, если это все сложно переписать, может быть это уже и не микросервис вовсе? И огромный микросервис, который выполняет большое количество бизнес-логики, превращается в мини-монолит. Да, это сервис, но не микросервис. В моем идеальном восприятии и я стараюсь работать именно так микросервис должен держать минимальную бизнес-логику. Он небольшая сущность, которую Java-команда может написать и переписать за спринт. И это не должно задеть какой-то другой функционал. Именно тогда речь идет о микросервисе.

Если же мы от этого уходим, ломается идеология. А если нам хочется сломать идеологию, то зачем мы вообще в это все ввязались, и как планируем работать дальше?

Как всегда, когда собрались архитекторы, происходит рефакторинг ради рефакторинга. Но нужен ли он здесь на самом деле, или хочется впихнуть то, что в формат микросервиса впихивать не нужно? В монолите мы привыкли к тому, что можно что-то переписать, поменять модуль, и все классно! Но чтобы отрефакторить монолит, которому 20 лет (а я с таким сталкивался в реальном мире, это не сказки), только для того, чтобы разобраться, как это сделать, нужно полгода. И это без учета времени на необходимые изменения.

Андрей Булов: Микросервисы copy & paste driven development. Согласно идеологии микросервисов, в них не должно быть общих зависимостей, кроме какого-нибудь спринга, или общих либ. Но почему-то все забывают о том, что когда микросервисы пишутся для энтерпрайза, пусть и не очень кровавого, у него есть enterprise-specific вещи. А есть еще базовые, типа общей аутентификации, общего логирования, общих доменных объектов.

В зависимости от упорства адептов микросервиса, мы будем либо копипастить весь этот код между нашими микросервисами, либо сделаем библиотеку, либо вынесем это в отдельный микросервис.

Я прекрасно помню кейс, когда мы деплоимся на какой-то init или prod, у нас собираются нормально десять микросервисов, а одиннадцатый бабах! падает. Мы забыли туда скопипастить наш общий user-объект, в котором есть пермиссии. И с матами, конечно, все это дело правим.

Поэтому от идеологии всегда приходится отступать, и делать либы. Но тогда это уже перестает быть микросервисом.

Очень трудно определить бизнес-контекст такого микросервиса. Например, аутентификация это бизнес или не бизнес? А общие объекты, которые валидны для всего приложения, или для всего энтерпрайз-ландшафта? И начинаются всякие интересные спекуляции.

За это я микросервисы не очень люблю.

Алексей Шарапов: В этом моменте я с тобой согласен, но не во всем. Мне нравится подход, когда библиотека выносится отдельно, и все ее куски делаются при помощи CTRL-C CTRL-V. С июля мы начали новый проект, в котором изначально используется микросервисный подход. И я слышал что-то подобное от наших архитекторов: либо мы копируем, либо выносим в библиотеки.

Но подключать библиотеку стоит, наверное, на стадии сборки самого микросервиса. А мы сейчас говорим про наш энтерпрайз Agile, и в этом нет ничего страшного. Это просто зависимость, которая будет выполнять близкий функционал. Либо к чему мы пришли только спустя четыре месяца работы стоит выносить этот функционал в отдельный микросервис.

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

Ты сам это проговорил, но неизвестно почему не захотел к этому прийти, несмотря на то, что понимаешь необходимость такого шага.

Андрей Булов: Собственно, именно поэтому: в микросервисах нет единого хорошего стандарта, а есть набор практик и адепты, каждый из которых агитирует за свое. Если микросервис разрабатывает программист или команда программистов, вы получите свой уникальный стиль микросервиса с такими вещами, как POST vs PUT (холивар на кухне), и рассуждениями о том, какие ошибки мы возвращаем при валидации, какое возвращаем время и в каком стиле мы возвращаем API.

Это требует либо постоянного ревью: чтобы пришел архитектор или лид-девелопер и вставил руки в нужное место, либо нужен общий гайдлайн на проект. Но опять же, общих best practices для микросервисов, к сожалению, нет. Адепты спорят друг с другом. И ты думаешь: Хм, разработчик Василий так любит двухсотый код возвращать, надо учесть эту специфику. А этот, наверное, 404 бросит. Ведь тут не сервер упал, просто у него код ошибки такой. Либо требуется централизованное управление, и тогда теряется весь смысл микросервисов. У тебя получается команда с многими модулями, которые просто деплоятся отдельно, и архитектор ходит и пишет для них гайдлайны.

Где эта хваленая независимость, когда команда может переписать микросервис за спринт? Необходимо много документации по описанию джейсонов, свайгеров и прочего, и много-много ревью. В монолите все это делать, наверное, проще.

Алексей Шарапов: А как вообще жить без документации? Я бы начал с этого, потому что я себе такого не представляю. Да, мысль, может быть, чуть-чуть испорчена энтерпрайз-сложным миром, большим и тяжелым. Но даже несмотря на микросервисную инфраструктуру и архитектуру, мне нравится документация. Под ней можно понимать не подробный талмуд о том, как мы должны написать микросервис, а описание общих частей.

Сейчас мы что-то подобное подготавливаем для наших команд. И я не вижу в этом ничего плохого. Там просто написано о том, что нужно использовать классические коды ошибок, как это описано в интернете.

По поводу всего остального. Во-первых, инфраструктура as a code становится проще. То есть деплой становится everything as a code, а все части деплоя, инфраструктуры и самого кода вы можете посмотреть в Гите. Разработчику проще, когда он деплоит какое-то количество микросервисов, и отлавливает эти ошибки быстрее. Ему не нужно лезть в тяжелый монолит, рассматривать его и пытаться понять, что происходит. Он понимает, что происходит от написания первой строчки до попадания на ProdStage, и на каждой отдельной части.

Плюс выпуск происходит намного быстрее, и ему легче свериться с документацией. Ему не нужно разбираться с внутренними взаимодействиями, с тем, как работает система. Он написал свою часть. Видит, с чем это все вместе работает, и может выпускать этот кусочек. С Андреем я согласен в одном: в команде должны быть люди, которые понимают, что они делают. Даже несмотря на кровавый энтерпрайз, они должны понять, что они создают микросервис по определенным законам. И все будет круто до тех пор, пока люди соблюдают установленные правила, хотя бы из взаимоуважения.

Андрей Булов: Да, давайте наймем команду космонавтов, которая нам все хорошо сделает.

О, мое любимое.

На самом деле картинка это практически реальный ландшафт системы и реальный кейс. Прибегает ко мне заказчик, говорит: Слушай, там бага. Из Гуя на проде неправильно заказ считается для такой-то модели машинки для немецкого рынка. Для остальных все хорошо работает. Вот тебе логи, прод не трогай. На деве это воспроизводится. И вот тебе данные.

На деве все хорошо. Значит, мне нужно поднять у себя Docker, кучу микросервисов с базой, учесть взаимодействие этого всего. А потом сидеть, как обезьянка, переключаться между PyCharm и смотреть, куда приведет тот или иной breakpoint. Потому что проблема очень скользкая, и просто логами ее вычислить невозможно.

С точки зрения вычислительных мощностей, поднять у себя такое количество докеров, конечно, можно, но тогда тормозить будет зверски. Если мы подключаемся к какому-нибудь Куберу и удаленно пробрасываем порты, конечно, оно может сработать. Но тогда получается, что один девелопер блокирует все девовское окружение, а другие сидят, курят бамбук или девелопят локально. Либо нам нужно много-много окружения, иначе необходимо много-много серверов. Что возвращает нас к первому вопросу: все это совсем не дешево.

А в-третьих, чтобы банально сграбить данные со всех этих микросервисов, из БД, мне нужно залезть в каждый, вытащить какие-то данные и посмотреть, совпадают ли они. Потому что у нас констрейнтов нет. А потом нужно это все себе залить, или залить на дев, поднять и посмотреть, чтобы заработало. Да, чтобы еще у меня port forward не умер в самый интересный момент, потому что процесс растянут во времени.

Поэтому дебажить микросервисы я люблю очень сильно!

Алексей Шарапов: Андрей прямо по больному прошелся. Конечно, дебажить микросервисы довольно-таки сложно. Но, на самом деле, команда должна просто привыкнуть к освоению новых инструментов.

В мыслях о port forwarding я с Андреем абсолютно не согласен. Если приходится пробрасывать огромное количество каких-то сущностей в единицу времени, наверное, мы опять говорим о том, что у нас слишком большое количество взаимодействий. Нужно вообще прекратить это дебажить, поднимая какие-то локальные контейнеры. Либо, необходимо иметь достаточное количество неймспейсов. Понимайте изначально, во что вы вписываетесь. Да, это может быть дорого. Вы можете поднять какой-нибудь свой minikube.

Кстати, мы жили с проектом для тестирования на minikube, и никто ни разу не пожаловался, что нам не хватает ресурсов. Есть какие-то локальные машинки, где-то можно что-то подешевле запустить с этим проблем быть не должно. Не нужно запускать столько сервисов, чтобы проверить это между собой в тесте.

Кроме того, можно прекратить создавать костыли, и позвать человека. Можно окружить все трассировкой, например использовать Jaeger, посмотреть, собирать логи с каждого момента. Логов не хватает: значит нужно посмотреть, как микросервисы взаимодействуют между собой. При нормальной трассировке можно обнаружить, где происходят падения. Придется поднять буквально несколько сервисов. И это займет не так много времени и ресурсов. И жизнь твоя улучшится.

К этому просто надо привыкнуть. Очень сложно осознать, что все поменялось извините, теперь будет так. Но когда привыкнешь, станет легче.

Андрей Булов: Видимо, я морально устарел в микросервисах.

Есть еще вот такой интересненький кейс:

У нас есть микросервис со своими бизнес-контекстами, сервис, который делает Order, сервис, хранящий в себе Vehicle. Есть API GW, есть GUI. К нам приходит продактоунер и говорит: Эй, ребята, мы принимаем заказы на машины, и теперь занимаемся отделкой салона.

И начинается парад независимости. Это когда команды внедряют у себя один параметр и проносят его через все независимо друг от друга.

А потом начинается игра: давайте все это дело проинтегрируем! Мы возвращаемся к предыдущему слайду: как это дебажить?

Очень тяжело и с первого, и с десятого раза определить реальный бизнес-контекст микросервиса и приложения. И во всяких крупных энтерпрайзах часто получается, что flow идет как бы через все микросервисы. Все они, вроде бы, независимые, но друг без друга не могут, и все должно работать вместе.

Это абсолютно реальный пример: нам никуда не деться от того, что придется пронести бедный параметр VehicleCover через все микросервисы и базы. Давайте это сделаем и помолимся, чтобы все программисты микросервисов назвали это правильно, соблюли чудесный capital letter, сделали везде одинаковый тип, воркчар был правильным, все это прошло ревью архитектора и т.д.

В монолите это сделать довольно легко: открываем идею, смотрим, даем кому надо по рукам профит! В микросервисах придется побегать между командами.

Алексей Шарапов: Я согласен с тем, что это будет боль. Но самое главное не создавать SOA в этом случае. Это же не микросервис: протаскиваешь через распределенные данные монолита из кусков какое-то значение, которое ты должен везде обработать. Почему твое значение не может быть отдельным микросервисом, из которого все берут данные? Или который это обрабатывает отдельно от всех, чтобы не нарушать состояние остального. Если такие требования появились, как их вписать со стороны идеологии? А если это вам не подходит, зачем вы вообще начали делать микросервисы?

По поводу зависимостей. Хочу вернуться к прошлому вопросу про копипаст, где нужно вставлять и описывать одну часть. Ты говоришь: не факт, что они правильно дадут название во всех своих сервисах. Именно для этого и нужна если не документация, то хотя бы минимальное описание, как с этим работать. Нужно просто предложить определенный алгоритм с этого дня: есть такие-то требования и проект может быть такого-то характера. А еще существует вероятность того, что этот проект изначально не был подготовлен для микросервисов.

Я такое видел: берут какой-то проект, для которого не нужны микросервисы. Но нет, мы просто обязаны сделать классно и красиво, ведь решение о необходимости микросервисов спустили сверху. Но ведь главное не применять технологии там, где они не нужны. Плохо делать что-то просто потому, что так захотелось.

Больше по этому поводу мне нечего сказать. Наверное, это вопрос ко все участникам разработки.

Андрей Булов: О, я тебя заразил здравым смыслом!

Тестирование.

Мой любимый вопрос на Lead Test Engineer или Test Manager. Я рисую такую картинку и говорю:

Это система, которая работает с деньгами пусть будет продажа машин. Если мы там что-то потеряем, человек не получит машину, а компания не получит деньги, плюс ее ждут репутационные издержки и т.д. Вопрос: как нам релизиться раз в спринт, не падать в проде и не попасть на штрафы? Напиши мне такой процесс тестирования, и я смогу убедить разработчиков написать тест. Но только напиши мне так, чтобы я был уверен хотя бы на 85%, что я в проде не упаду.

На этот вопрос, к сожалению, пока мало, кто ответил. Все почему-то говорят про модульные тесты, про то, что нам нужно окружение, еще одно окружение, еще одно окружение.

Конечно, правильно было бы иметь какой-то хороший пре-прод, в котором мы все это тестируем. Но это не всегда возможно. В классической разработке с классическими программистами, тест-лидами, менеджерами и т.д., мы имеем все эти dev-test, int, какое-нибудь staging-окружение, куда мы релизимся по определенному процессу. И мы должны понимать, что у нас все это будет протестировано.

Ни технически, ни организационно идеальных практик пока, к сожалению, нет. В общем, тяжело это работает. С монолитом проще: взяли Selenium, все протестировалось, смоками покрыли, выкатываемся в прод все работает. Мы красавцы, мы восхитительны!

Алексей Шарапов: А как же без проблем, Андрей? Может быть, в том, что касается тестирования, я с тобой согласен. Я не то чтобы заразился здравым смыслом. Просто не так глубоко погружался в проблемы тестирования.

И я еще раз призываю прекратить думать о микросервисе, как о монолите. Мы привыкли тестить так, чтобы было красиво, но теперь условия изменились. Мы, например, во время тестирования очень активно используем testcontainers. И это решает часть проблем.

Я все время говорю о том, что нужно иметь достаточное количество стендов. Я хожу в свои команды и напоминаю: Ребят, поднимите нормальное количество стендов, прекратите страдать на одном, который упал, после чего все сломалось, и вы мучаетесь. Распределите запросы, и страдания закончатся. Человек, который у вас близко работает с инфраструктурой, как мне кажется, должен взаимодействовать и с и с девелопмент командой. Хотя бы для того, чтобы подойти и сказать им: Поднимите стенды, все пробросьте к себе на машину, используйте testcontainers, прекратите тестить это, как монолит, и все будет хорошо.

Не надо тащить за собой опыт монолита, применять его на микросервисах и говорить блин, ничего не работает, как нам теперь жить, и что же с этим делать?

Частично, Андрей, я с тобой согласен, но и монолит не отменяет множества стендов. Я не могу себе представить отчаянных людей, которые запустили монолит на одной машине, чтобы сэкономить свои ресурсы, и сказали: Все классно! Мы никогда не падали, а во время деплоя там огромный downtime.

Андрей Булов: Уел!

Хочу рассказать про каждому разработчику по своему Куберу. CI/CD моя любимая тема.

Во-первых, чтобы это все собрать, нам нужен очень хороший Jenkins с кучей слейвов. В разработке возникает несколько вопросов:

  • Мы пересобираем все сервисы каждый коммит?

  • Сколько нужно слейвов на сборку?

Приходит бизнес и говорит:

А сколько нам нужно заплатить за сборку? Сколько-сколько? Нет, вон там стоит под столом сервер, давайте его использовать.

  • А почему все так медленно работает?

У меня пять разработчиков сделали коммиты, и пять раз подряд пересобирается весь этот зоопарк.

Помимо очень мощного окружения нужен очень мощный CI/CD.

  • Можем ли мы считать, что у нас работает система, когда собралось 60 микросервисов, и 61, который мы не релизим, упал?

У меня вопрос: можем мы зарелизиться, или нет?

Тот сервис, конечно, релизить не будем, остальные зарелизим. Какая радость от того, что мы в проде упадем?

А нужно ли вообще смотреть, что с этим микросервисом? Мы его уже 100 лет не трогали, что-то упало.

Ну, не знаю. Может быть, сам заработает.

С continuous delivery отдельная песня, когда нам нужно заделиверить что-то. Мы деливерим, деливерим, деливерим это в прод бах! падает какая-нибудь джоба, нам это нужно пересобирать все по новой, и т.д. В общем, это гораздо больнее, чем собрать один Maven clean install, прогнать все тесты все работает, мы великолепны.

Алексей Шарапов: А как жить без CI/CD? Попробую описать, что я имею в виду.

Мне кажется, что CI и CD необходимы для любого проекта. Ты используешь CI в проекте с монолитом, с микросервисами. Почему появляется необходимость на каждый коммит пересобирать все-все-все микросервисы? Здесь стоит опять задуматься о независимости. Возможно, разговор тут идет не про инструменты. Однако, предположим, какой-нибудь GitLab CI с его Docker runners сильно сэкономили бы тебе ресурсы. Мы не говорим про этот страшный Jenkins, который перегружен, огромную Java-машину. Мы можем использовать что-то более легковесное.

Может быть, каждый CI/CD должен заканчиваться на том моменте, где это на самом деле необходимо. Если речь идет об огромном монолите, который работает в нашем энтерпрайзе, скажу честно, CD у нас поскольку постольку, просто потому что есть такие условия. Однако же мы предоставляем и такой инструмент. И мы не берем jenkins , как мы привыкли, а находим необходимый инструмент легковесный, удобный. Именно с его помощью мы что-то делаем, и это классно работает.

Я просто не могу себе представить, как можно жить без CI/CD. У нас микросервисы это огромный проект, все они собирались отдельно. Был микросервис, который жил с самой первой версии, никогда не менялся, мы его не пересобирали, однако же он всегда работал. Вот она независимость.

Андрей Булов: О, вот это мой любимый вопрос на собеседовании отдельные DevOps команды.

Допустим, у нас есть вполне себе микросервисный ландшафт с базами под каждый микросервис. Все это в consistency состоянии находится, все прямо по матчасти. Приходит заказчик и говорит: Пожалуйста, перед выкаткой сделайте бэкап прода. И сделайте нормально, чтобы транзакции загасились, мы все забэкапили, сохранили и дальше накатывали, потому что деньги, заказы страшно.

Мой любимый вопрос DevOpsам: как написать такую чудесную синюю кнопку, которую жмешь, все базы в один момент с каким-то снепшотом бэкапятся. А еще все это можно потом либо восстановить одной зеленой кнопкой, либо слить разработчикам на дев-окружение. Причем мне нужно не ощущение: Ну, в принципе, нормально! Вроде, все закончилось, а что-то более доказательное. Если бизнес говорит: Ребята, это какая-то фигня, что мы ему можем возразить в ответ? Что, по нашим ощущениям, все должно работать?

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

Алексей Шарапов: Нет, потому что это один из самых сложных вопросов касательно микросервисов.

Есть разные подходы на данный момент. Предположим, что существует сложная система с балансировкой через Patroni. Мы в наших реалиях никому не можем передать имеющиеся snapshot базы, просто потому что это невозможно.

Нужно использовать грамотно балансировку, геораспределенный кластер. Когда вы уверены, что ваша хорошая балансировка на 90% обезопасит от всех проблем, вам будет легче. А в ситуации, когда грохнулось все, развалился гео-кластер, машины упали во всех частях, в такой момент то, что у тебя на одну транзакцию меньше забекапилось, как мне кажется, это меньшая из проблем.

То есть нужно постараться максимально избегать ситуации, когда все это придется в огне восстанавливать, и это уже решит часть твоих проблем. Я обычно делаю ставку именно на это. Но, на самом деле, подходов много. Когда приходишь, а тебе говорят: Мы сделали одну базу, она крутится, все к ней обращаются. А у нас микросервисы, что теперь делать?, бывает страшно. Об это можно открыть отдельную дискуссию.

Андрей Булов:

Микросервисы просто математически дольше создавать, чем монолит. Нужно написать исходящий интерфейс, входящий интерфейс, обработку ошибок на обеих сторонах, и это все должно как-то вместе срастись. В продакшен какие-то PoC MVP быстрее писать в одной кодовой базе, в одном гите, и не гонять ресты.

К сожалению, в бизнесе с религиозным рвением верят в то, что каким-то образом можно стать лучше, быстрее, зарабатывать в пять раз больше денег, просто потому, что система написана на микросервисах. И есть технари, которые хотят написать микросервисы, потому что: Я же никогда не делал так давайте попробуем!. И они совершенно не обращают внимания на то, что до этого они десять лет занимались монолитами.

Получается, все то, про что я говорил: все выливается в эти проблемы. Используйте паттерн мудро и только там, где это необходимо. Аминь.

Алексей Шарапов: Абсолютно согласен не нужно применять микросервисы там, где этого не требуется. Я хочу привести пример того, как я это представляю. Мы не можем запустить проект в продакшен, пока не будет написано большое количество бизнес-логики. Но мы можем посмотреть на это с другой стороны: у нас есть простой бизнес. Предположим, я сейчас делаю автоматическое создание ресурсов внутри нашей сети.

Крошечный скейтбордик это первый маленький микросервис, который дергает по REST какой-нибудь AWX и запускает создание первой машины: класс, продукт уже есть, и я могу пользоваться этим каждый день. Потом я хочу сделать самокат. Прикручиваю туда базу данных, чтобы ходить в стейты. Дальше велосипед, мотоцикл, в конце машина это уже AWX плюс Terraform, Cloud, которые взаимодействуют между собой через разные микросервисы, Kafka. Я могу создавать какие-то вещи уже с первой улыбающейся рожицы, которая на меня смотрит (LIKE THIS).

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

Я предлагаю применять паттерны, подходы, архитектуру там, где это действительно нужно, а не разбивать монолит на куски в ожидании, когда это все вместе будет отработает огромную транзакцию. Тут все зависит от проекта. У меня работает скейтборд, я с ним счастлив и знаю, что послезавтра самокат будет уже готов.

Профессиональная конференция по интеграции процессов разработки, тестирования и эксплуатации DevOpsConf 2021 пройдет 30 и 31 мая 2021. Но билеты на нее вы можете приобрести уже сейчас, успев сделать это до повышения цены.

А еще вы можете сами стать героями конференции, подав доклад.

Хотите бесплатно получить материалы предыдущей конференции по DevOps? Подписывайтесь на рассылку.

Подробнее..

История Учи.ру от мини-монолитов до микросервисной архитектуры

31.03.2021 14:23:38 | Автор: admin

Добрая четверть моего рабочего времени за последний год ушла на обновление архитектуры Учи.ру. С ростом продуктов и количества пользователей увеличился и клубок зависимостей в монолите. Выделяя из него части и набивая на этом пути шишки, я не раз задумывался о том, как мы к этому пришли. Волей-неволей вспоминаешь, с чего все начиналось.

В этом посте я попробовал собрать историю архитектуры Учи.ру. В нем нет фрагментов кода и исчерпывающих технических подробностей. О нашем опыте выделения микросервисов для решения некоторых задач образовательной платформы в следующих публикациях.

Геометрическое совершенство монолита воспринималось людьми как некий безмолвный вызов, оно поражало не меньше, чем другие свойства загадочной находки.

Артур Чарльз Кларк. 2001: Космическая одиссея (1968)

Мне кажется, практически любой стартап начинается с архитектуры простого типа и со временем усложняется. Сегодня мы работаем с довольно сложной разветвленной системой, которая постоянно разрастается.

Актуальная схема Учи.ру и распределение сервисовАктуальная схема Учи.ру и распределение сервисов

Начиналось же все с маленького сайта около десяти лет назад.

С чего все начиналось

Эра мини-монолитов

Первые версии Учи.ру появились в начале второго десятилетия ХХI века. Это были очень простые сайты с отдельными базами данных, образовательным контентом и менеджментом: старая платформа Учи.ру с уроками, Учи.ру Столбики и Учи.ру Колонки. Спустя десятилетие они выглядят немного старомодно, но все равно мило мы храним их во внутреннем музее славы Учи.ру и публичный доступ к ним не предоставляем.

Так выглядело задание на сайте Учи.ру Столбики там дети учились считать в столбик.Так выглядело задание на сайте Учи.ру Столбики там дети учились считать в столбик.Еще несколько исторических документов.
В Столбиках уже можно было получать ачивки за учебу.В Столбиках уже можно было получать ачивки за учебу.А список уроков на старой платформе Учи.ру выглядел довольно просто.А список уроков на старой платформе Учи.ру выглядел довольно просто.

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

Эра зарождения первого монолита

До 2012 года сайты существовали обособленно. Затем мы создали новую платформу с единой точкой входа Login, которая поглотила старую Учи.ру и Колонки. Столбики ждало скорое забвение.

Изменения и перенос контента породили проблемы вроде конфликта стилей, что сказывалось на качестве. Тогда команда впервые задумалась о создании эталонной системы управления контентом CMS.

Эра CMS

Через два года системная архитектура выглядела скромно: CMS, основная платформа, а также разные прикладные модули, например, для аудита, управления персоналом, временного трекинга.

Довольно простая CMS помогала в совместном создании и версионировании контента для пользователей, основу которого составили интерактивные карточки (задания) для детей, разработанные совместно с методистами.

Расширение функционала основного модуля

На первых стадиях разработка шла очень быстро, преимущественно мы использовали модель Водопад. На том этапе усложнять архитектуру не было смысла, ведь никто не знал, к чему мы придем в итоге.

Изначально мы старались разделить ответственность. Так, часть задач мы реализовали в виде функций CMS, таких как управление уроками или разработка методических материалов. Но когда темпы выросли, практически все новое стало добавляться в uchiru-login, просто потому что так было быстрее. Постепенно усложняя этот компонент, мы получили монолит. Чем дальше, тем больше его размеры и высокая степень связности затрудняли дифференциацию различных функциональных элементов.

Из-за сложностей с любыми модификациями в монолите в начале 2019 года мы работали с устаревшими версиями Rails (4.1) и Ruby (2.1.5). Webpack с небольшими вкраплениями React-компонентов не позволял легко обновить зависимости без существенных рисков отказа в обслуживании. Нужно было что-то делать

Выделение функций из состава монолита

Чтобы прощупать возможности разделения, мы начали проводить эксперимент по разъединению фронтенда и бэкенда. К этому моменту интерфейс представлял собой классические Rails-шаблоны с примесью старого Webpack. И хотя мы не ставили глобальной задачи по переходу на микросервисы, этот опыт все же стал большим шагом для нашей команды сразу в техническом, инфраструктурном и организационном плане. Но самое главное, мы начали выделять компоненты из uchiru-login. Стало понятно, что обуздать монолит реально. Отправной точкой стало выделение откровенно обособленного функционала с минимальной степенью связности. На подобных некорневых блоках мы и сосредоточили усилия.

  1. Генератор PDF-сертификатов. Попрактиковались мы на микросервисе, который должен выдавать готовый документ по входным параметрам. Фактически мы сделали классический распределенный монолит с синхронным сетевым взаимодействием.

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

  3. Развивающие игры. Используя опыт олимпиадников, мы создавали игры как отдельный компонент, связанный с монолитом авторизацией, но способный развиваться самостоятельно.

  4. Модуль доступа к данным. Перед тем как что-то отделить, мы проделали большую работу по устранению связности компонентов системы. Только в процессе выпиливания олимпиадной платформы мы нашли около десяти устаревших таблиц и сущностей и удалили их, когда выделили функционал в отдельный проект, а ведь во всем монолите есть и другие.

    Сначала монолит и новый сервис использовали общую базу данных. Мы старались по возможности переносить операции записи ответственных данных в новые БД, а из монолита использовать их в режиме чтения.

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

    Для разработки этого модуля мы использовали библиотеку JSONAPI Resources, которая сочетает в себе гибкость, низкую скорость и синтаксис, очень похожий на классический ActiveRecord. Залогом успеха стало стремление группы энтузиастов, которые во что бы то ни стало хотели достичь нужного эффекта.

Справляемся с высокими нагрузками

Дальше на пути разделения сервиса нас настиг карантин, который стал новым испытанием для компании в целом и нашей команды в частности. Нелинейный рост трафика обнажил узкие места синхронной распределенной архитектуры и монолита. Система переставала справляться с потоком запросов, а времени на реагирование было очень мало, потому что на рынке началась жесткая конкуренция и борьба за выживание.

  1. Кеширование. Это было первое, что пришло в голову. В качестве инструмента мы использовали Redis. Чтобы не заниматься поддержкой кластера в облаке, мы решили заменить его урезанной версией Redis от Envoy с шардированием по ключу хранения. В результате система стала держать нагрузку лучше, но это было только начало.

  2. Реплики БД. После очередного скачка трафика мы уперлись в лимит пула соединений с БД. Теоретически работа с микросервисами должна была помочь в масштабировании самых нагруженных частей системы или вовсе избежать этой проблемы. Но это в идеальном мире.

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

  3. Octopus. К счастью, на помощь нам пришел Octopus, но и он не обрабатывал все случаи, особенно те версии, которые были совместимы с устаревшей платформой. Например, мы обнаружили, что запись в режиме реплики тянет за собой все ассоциативные связи в том же режиме. Это порождает конфликты, связанные с попытками записи в read-only-транзакциях. Пришлось заниматься monkey-патчингом ORM-компонентов. Методом проб и ошибок проблему решили.

  4. Оптимизация обработки запросов. Следующим отказало синхронное межсервисное взаимодействие. Поскольку основная часть трафика традиционно проходила через главную страницу сайта и кабинет ученика, сборка страницы осуществлялась на сервере. При формировании страничек подобного типа приходится дергать несколько сервисов для получения нужной информации, например, недавно выделенный олимпиадный.

    Это сыграло с нами злую шутку, потому что обработка таких запросов стала происходить крайне медленно. Впрочем, именно решение этой проблемы вывело нас на качественно новый уровень.

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

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

Боевое крещение Circuit breaker.Боевое крещение Circuit breaker.

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

Разделение на микросервисы действительно возможно

Но ведь верилось же! Казалось, еще немного усилий и то самое светлое будущее, которое каждый представлял себе по-разному, в зависимости от воспитания и фантазии, обязательно наступит.

Артур Чарльз Кларк. 2001: Космическая одиссея (1968)

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

В любом случае мы оценили преимущества асинхронной архитектуры и распределенных систем, а главное убедились на своем опыте, что распилить запутанный монолит вполне реально. При этом стало понятно, что ответственность это не одностороннее понятие и для успешного развития платформы бизнес должен с пониманием относиться к проблемам технических отделов, оставляя время и ресурсы на устранение долгов. А IT-специалистам не стоит скромничать нужно заявлять о такой потребности, чтобы была возможность вовремя провести субботник. Лично я теперь убежден, что выявление некоторого стабильного фундамента системы из нескольких сервисов позволит нам унифицировать платформы, а также решить проблему мертвого кода.

Подробнее..

Перевод Архитектура микросервисов Разрушение монолита

01.06.2021 20:15:10 | Автор: admin

Мы расскажем о том, как можно разбить монолитное приложение на более мелкие части, составляющие модульную систему, и обсудим миграцию в облако.

Эта статья подводит итог вебинара "Разрушение монолита", представленного Даниэлем Гутьерресом Сааведрой, старшим инженером-программистом компании Zartis. Вы можете посмотреть полный текст вебинара, который также включает сессию вопросов и ответов, ниже!

Вы работаете с монолитными системами и унаследованными приложениями? Вы ищете способы модернизировать свою архитектуру и перейти на микросервисы? В этой статье мы расскажем о том, как можно разбить монолитное приложение на более мелкие части, которые образуют модульную систему.

Почему стоит выбрать микросервисы

Микросервисы разрабатываются с использованием бизнес-ориентированных API для инкапсуляции основных бизнес-возможностей. Принцип слабой связи (loose coupling) помогает устранить или минимизировать зависимости между сервисами и их потребителями.

Кроме всего прочего, они являются:

  • Масштабируемыми

  • Управляемыми

  • Поставляемыми

  • Гибкими

В конце концов, архитектуру микросервисов намного проще тестировать и развертывать. Если мы добавим к уравнению подход DevOps, где у нас есть очень маленькие части кода, которые можно тестировать и развертывать небольшими порциями, преимущества станет невозможно игнорировать.

Проблемы микросервисов

Здесь важно признать, что архитектура микросервисов действительно сопряжена с некоторыми трудностями. Существует несколько дополнительных уровней сложности, поскольку в системе будет много подвижных частей, и тестирование микросервисов может оказаться сложным.

Вот некоторые из основных проблем, которые необходимо учитывать:

  • Дополнительные уровни сложности.

  • Если ваше программное обеспечение не меняется часто, оно может ничего не исправить.

  • Приобретение новых продуктов требует дополнительных затрат.

  • Как только вы переходите в облако, это позволяет вам выполнять дополнительные действия, такие как ведение журналов, дополнительные меры безопасности и т.д. Ваша команда должна будет самостоятельно обучиться использованию этих инструментов.

Разрушение монолита

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

Шаг 1: Определение основных услуг

Целесообразно начать миграцию с определения критически важных сервисов, которые могут быть теми, что приносят наибольший доход вашему бизнесу, или часто используются вашей клиентской базой. Эти службы будет труднее всего отделить от монолита.

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

Для примера возьмем проектирование, управляемое доменом (Domain-Driven Design, DDD). В микросервис-ориентированной системе, возможно, наш домен очень большой, который может охватывать множество микросервисов, и они могут функционировать как поддомены. Таким образом, это весьма схожий подход к проектированию систем, и он прекрасно совместим с такими вещами, как DDD, BDD и т.д.

Шаг 2: Разделение и рефакторинг

Итак, мы увидели, как можно все разделить, но как теперь отделить сервисы от всего остального и рефакторить их, чтобы они стали набором микросервисов?

Первое, что нужно знать: чем меньше коммуникаций, тем лучше отношения. Очень легко и заманчиво создать множество сервисов, которые удобно тестировать по отдельности, но в целом ваша система станет сложной и запутанной. Это затрудняет отслеживание в случае появления проблемы, поскольку возникает огромная путаница, и может быть трудно определить, где кроется корень проблемы.

Еще одним важным моментом является внесение событий в очередь. Нам много раз говорили, что мы не можем разбить их на отдельные службы, потому что это идеально синхронизировано для событий, которые происходят на следующих этапах. Обычно это не так. Благодаря системам очередей и обмена тематическими сообщениями, которые существуют сегодня, есть множество способов нарушить синхронизацию. Это правда, что вы добавляете дополнительный слой, который может принести некоторые проблемы с задержками, но в конечном итоге возможность нарушить всю синхронность, вероятно, улучшит ваш результат.

Шаг 3: API и облако

Теперь, когда мы сделали все нарезки и разделили наш код, куда мы можем поместить все это? В облако!

Сегодня у нас есть множество решений, и это лишь малая часть того, что предоставляет нам облако.

Если назвать несколько наиболее распространенных, то Google Cloud (GCP), Microsoft Azure и AWS это три основных претендента, но есть и много других поставщиков. Эти решения обычно предоставляют готовую архитектуру микросервисов, где вам нужно только сделать несколько штрихов и провести небольшое обучение, чтобы все заработало.

Кроме того, есть решения, которые необходимы на месте, потому что вы не хотите размещать свои сервисы в облаке. Например, применив сервисы Spring Cloud, можно использовать свои собственные серверы и идеально имитировать структуры публичного облака.

Сколько может стоить миграция на микросервисы с использованием облачных решений?

Очень легко продолжать создавать микросервисы в облаке, но если у вас нет четкого плана, то возможно потерять контроль над бюджетом проекта. Если вы хотите получить оценку того, сколько вы можете потратить на облачные услуги, то для этого есть несколько способов.

Используя калькуляторы, предоставляемые большинством облачных сервисов, которые очень подробны, вы можете получить хорошую оценку, но для этого вам нужно иметь очень четкое представление о том, какова ваша клиентская база, объем транзакций, объем данных, кода и т.д. Если у вас есть все эти параметры, то можно достоверно оценить какими будут ваши затраты в облаке.

К сожалению, этот способ расчета не подходит к локальным провайдерам, таким как Spring Cloud services, которые несут различные расходы, связанные с наличием локального сервера.

Распространенные стратегии миграции

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

Шаблон Strangler

Одним из способов миграции может быть использование паттерна strangler в случае, если ваше приложение очень большое. Таким образом, вы сможете выделить наиболее важные сервисы в архитектуру микросервисов.

В приведенном ниже случае было решено извлечь всю клиентскую часть приложения в архитектуру микросервисов и оставить административную часть в монолите, что вполне нормально. Здесь значительно расширили свой код и смогли сделать это, не останавливая разработку. Но это не должно быть окончательным состоянием приложения.В идеале все должно оказаться в правой части изображения. Как вы можете видеть, там есть DBF, то есть DB (база данных) для каждой службы. Это не обязательное требование, но оно помогает.

Параллельная разработка

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

Основной подводный камень этого подхода заключается в том, что он обычно удваивает объем технического обслуживания и дублирования кода, но в конечном итоге все будет в правой части экрана, и если вы хотите сократить риски, этот метод может сильно помочь.

Заключение

Когда мы находимся в процессе миграции, важно не забегать вперед и пытаться вносить изменения параллельно или проектировать их заранее.

Представьте, что вы работаете над параллельной миграцией и решили выполнять миграцию параллельно с разработкой; если появится новая функциональность или возможность, вам придется дублировать этот код и выполнять работу дважды. Если вы попытаетесь спланировать миграцию заранее, одновременно внося изменения в ваше основное приложение, вам будет трудно избежать осложнений.


Перевод статьи подготовлен в рамках курса "Microservice Architecture". Если вам интересно узнать о курсе подробнее, приходите на день открытых дверей онлайн, где преподаватель расскажет о формате и программе обучения.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru