Микросервисы (Microservices)

Від перекладача: деякі скоріше всього вже читали цю титанічну працю від Мартіна Фаулера і його колеги Джеймса Льюїса, але я все ж вирішив зробити переклад цієї статті. Тренд микросервисов набирає обертів у світі enterprise розробки, і ця стаття є найціннішим джерелом знань, по суті витягами існуючого досвіду роботи з ними.

Термін «Microservice Architecture» отримав поширення в останні кілька років як опис способу дизайну додатків у вигляді набору незалежно розгортання сервісів. У той час як немає точного опису цього архітектурного стилю, існує якийсь загальний набір характеристик: організація сервісів навколо бізнес-потреб, автоматичне розгортання, перенесення логіки від шини повідомлень до приймачів (endpoints) і децентралізований контроль над мовами і даними.

«Микросервисы» — ще один новий термир на галасливих вулицях розробки ПО. І хоча ми зазвичай досить насторожено ставимося до всіх подібних новинок, конкретно цей термін описує стиль розробки ПО, який ми знаходимо все більш і більш привабливим. За останні кілька років ми бачили безліч проектів, що використовують цей стиль, і результати з цих пір були досить позитивними. Настільки, що для більшості наших колег цей стиль стає основним стилем розробки ПО. На жаль, існує не так багато інформації, яка описує, чим же є микросервисы і як застосовувати їх.

Якщо коротко, то архітектурний стиль микросервисов — це підхід, при якому єдине додаток будується як набір невеликих сервісів, кожен з яких працює у власному процесі і комунікують з іншими використовуючи легковагі механізми, як правило HTTP. Ці сервіси побудовані навколо бізнес-потреб і розгортаються незалежно з використанням повністю автоматизованої середовища. Існує абсолютний мінімум централізованого управління цими сервісами. Самі по собі ці сервіси можуть бути написані на різних мовах і використовувати різні технології зберігання даних.

Для того, щоб почати розповідь про стилі микросервисов, найкраще порівняти його з монолітом (monolithic style): додатком, побудованому як єдине ціле. Enterprise додатки часто включають три основні частини: користувальницький інтерфейс (складається як правило з HTML сторінок і javascript-а), база даних (як правило реляційної, з безліччю таблиць) і сервер. Серверна частина обробляє HTTP запити, виконує доменну логіку, запитує і оновлює дані в БД, заповнює HTML сторінки, які потім відправляються браузеру клієнта. Будь-яка зміна в системі приводить до пересборке і розгортання нової версії серверної частини програми.

Монолітний сервер — досить очевидний спосіб побудови подібних систем. Вся логіка по обробці запитів виконується в єдиному процесі, при цьому ви можете використовувати можливості вашого мови програмування для розділення програми на класи, функції і namespace-и. Ви можете запускати і тестувати програму на машині розробника і використовувати стандартний процес розгортання для перевірки змін перед публікацією їх у продакшн. Ви можете масштабувати монолітне додатки горизонтально шляхом запуску декількох фізичних серверів за балансировщиком навантаження.

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

image

Ці незручності призвели до архітектурного стилю микросервисов: побудови додатків у вигляді набору сервісів. У доповнення до можливості незалежного розгортання і масштабування кожен сервіс також отримує чітку фізичну межу, яка дозволяє різним сервісів бути написаними на різних мовах програмування. Вони також можуть розроблятися різними командами.

Ми не стверджуємо, що стиль микросервисов це інновація. Його коріння сягає далеко в минуле, як мінімум до принципів проектування, використаним в Unix. Але ми тим не менш вважаємо, що недостатньо людей беруть до уваги цей стиль і що багато програм отримають переваги якщо почнуть застосовувати цей стиль.

Властивості архітектури микросервисов

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

Розбиття через сервіси
Протягом всього терміну перебування в індустрії ми бачимо бажання будувати системи шляхом з'єднання разом різних компонент, багато в чому так само, як це відбувається в реальному світі. За останні пару десятків років ми бачили великий ріст набору бібліотек, використовуваних в більшості мов програмування.

Говорячи про компонентах, ми стикаємося з труднощами визначення того, що таке компонент. Наше визначення такого: компонент — це одиниця програмного забезпечення, яка може бути незалежно замінена або оновлено.

Архітектура микросервисов використовує бібліотеки, але їх основний спосіб розбиття програми — шляхом ділення його на сервіси. Ми визначаємо бібліотеки як компоненти, які підключаються до програми і викликаються нею в тому ж процесі, в той час як сервіси — це компоненти, що виконуються в окремому процесі і коммуницирующие між собою через веб-запити або remote procedure call (RPS).

Головна причина використання сервісів замість бібліотек — це незалежне розгортання. Якщо ви розробляєте додаток, що складається з кількох бібліотек, які працюють в одному процесі, будь-яка зміна в цих бібліотеках призводить до переразвертыванию всього програми. Але якщо ваш додаток розбите на кілька сервісів, то зміни, що зачіпають якої-небудь з них, зажадають переразвертывания тільки змінився сервісу. Звичайно, якісь зміни будуть зачіпати інтерфейси, що, в свою чергу, вимагає деякої координації між різними сервісами, але мета гарної архітектури микросервисов — мінімізувати необхідність такої координації шляхом встановлення правильних кордонів між микросервисами, а також механізму еволюції контрактів сервісів.

Інший наслідок використання сервісів як компонент — більш явний інтерфейс між ними. Більшість мов програмування не мають доброго механізму для оголошення Published Interface. Часто тільки документація і дисципліна запобігають порушення інкапсуляції компонентів. Сервіси дозволяють уникнути цього через використання явного механізму віддалених викликів.

Тим не менше, використання сервісів подібним чином має свої недоліки. Віддалені виклики працюють повільніше, ніж виклики в рамках процесу, і тому API повинен бути менш деталізованим (coarser-grained), що часто призводить до незручності у використанні. Якщо вам потрібно змінити набір відповідальностей між компонентами, зробити це складніше із-за того, що вам потрібно перетинати кордони процесів.

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

Організація навколо потреб бізнесу
Коли велика програма розбивається на частини, часто менеджмент фокусується на технологіях, що призводить до утворення UI команди, серверної команди і БД команди. Коли команди розбиті подібним чином, навіть невеликі зміни віднімають багато часу з-за необхідності крос-командної взаємодії. Це призводить до того, що команди розміщують будь-яку логіку на тих шарах, до яких мають доступ. Закон Конвея (conway's Law) в дії.

«Будь-яка організація, яка проектує якусь систему (в широкому сенсі) отримає дизайн, чия структура копіює структуру команд у цій організація»
— Melvyn Conway, 1967

image
Закон Конвея (conway's Law) в дії

Микросервисный підхід до розбивання передбачає раазбиение на сервіси згідно з потребами бізнесу. Такі сервіси включають в себе повний набір технологій, необхідних для цієї бізнес-потреби, в тому числі інтерфейс, хранилице даних і будь-які зовнішні взаємодії. Це призводить до формування крос-функціональних команд, що мають повний набір необхідних навичок: user-experience, бази даних і project management.

image
Сервісні кордону, підкріплені кордонами команд

Одна з компаній, організованих у цьому стилі — www.comparethemarket.com. Крос-численні функціональні команди відповідають за побудову і функціонування кожного продукту і кожен продукт розбитий на кілька окремих сервісів, що спілкуються між собою через шину повідомлень.

Великі монолітні програми теж можуть бути розбиті на модулі навколо бізнесових потреб, хоча зазвичай цього не відбувається. Безумовно, ми рекомендуємо великим командам будувати монолітні додатки саме таким чином. Основна проблема тут у тому, що такі програми мають тенденцію до організації навколо занадто великої кількості контекстів. Якщо моноліт охоплює безліч контекстів, окремим членам команд стає занадто складно працювати з ними з-за їх великого розміру. Крім того, дотримання модульних кордонів в монолітному додатку вимагає суттєвої дисципліни. Явно окреслені межі компонент микросервисов спрощує підтримку цих кордонів.

Наскільки великими повинні бути микросервисы?
Хоча термін «Микросервис» став популярним назвою для цього архітектурного стилю, саме ім'я призводить до надмірного фокусу на розмірі сервісів і суперечкам про те, що означає префікс «мікро». У наших розмовах з тими, хто займався розбиттям на микросервисы, ми бачили різні розміри. Найбільший розмір був у компаній, що слідували правилу «Команда двох піц» (команда, яку можна нагодувати двома піцами), тобто не більше 12 осіб (прим. перекл.: слідуючи цьому правилу, я в команді повинен бути один). В інших компаніях ми бачили команди, у яких шестеро осіб підтримували шість сервісів.

Це приводить до питання про те, чи є суттєва різниця в тому, скільки чоловік має працювати на одному сервісі. На даний момент ми вважаємо, що обидва цих підходи до побудови команд (1 сервіс на 12 осіб і 1 сервіс на 1 людину) підходять під опис микросервисной архітектури, але можливо ми змінимо свою думку в майбутньому. (прим. перекл.: з часів статті з'явилося безліч інших статей, що розвивають цю тему; найбільш популярним зараз вважається думка про те, що сервіс має бути настільки великим, щоб він міг повністю «вміститися в голові розробника», незалежно від кількості рядків коду).

Продукти, а не проекти
Більшість компаній по розробці ПО, які ми бачимо, використовують проектну модель, в якій метою є розробка певної частини функціональності, яка після цього вважається завершеною. Після завершення ця частина передається команді підтримки і проектна команда розпускається.

Прихильники микросервисов цураються цієї моделі, стверджуючи, що команда повинна володіти продуктом протягом всього терміну його життя. Коріння цього підходу йдуть до Амазону, у компанії є правило "ви розробили, вам і підтримувати", при якому команда розробки бере повну відповідальність за ЗА в продакшне. Це призводить до того, що розробники регулярно спостерігають за тим, як їх продукт веде себе в продакшне, і більше контактують з користувачами, оскільки їм доводиться брати на себе як мінімум частину обов'язків з підтримки.

Мислення в термінах продукту встановлює зв'язок з потребами бізнесу. Продукт — це не просто набір фіч, які необхідно реалізувати. Це постійні стосунки, мета яких — допомогти користувачам збільшити їх бізнес-можливості.

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

Розумні приймачі і дурні канали передачі даних (Smart endpoints and dumb pipes)
При налагодженні комунікацій між процесами ми багато разів були свідками того, як в механізми передачі даних містилася значна частина логіки. Гарним прикладом тут є Enterprise Service Bus (ESB). ESB-продукти часто включають в себе витончені можливості по передачі, оркестровки та трансформації повідомлень, а також застосування бізнес-правил.

Ком'юніті микросервисов віддає перевагу альтернативний підхід: розумні приймачі повідомлень і дурні канали передачі. Додатки, побудовані з використанням микросервисной архітектури, прагнуть бути настільки незавимыми (decoupled) і сфокусировнными (cohesive), наскільки можливо: вони містять власну доменну логіку і виступають більше в якості фільтрів в класичному Unix-ому значенні — отримують запити, застосовують логіку і відправляють відповідь. Замість складних протоколів, таких як WS-* або BPEL, вони використовують прості REST-ові протоколи.

Два найбільш часто використовуваних протоколу — це HTTP запити через API ресурсу і легкий месседжинг. Найкраще вираження першого дав Ian Robinson: «Be of the web, not behind the web».

Команди, практикуючі микросервисную архітектуру, використовують ті ж принципи і протоколи, на яких побудована всесвітня павутина (і, по суті, Unix). Часто використовувані ресурси можуть бути закешированы з дуже невеликими зусиллями з боку розробників або IT-адміністраторів.

Другий часто використовуваний інструмент комунікації — легка шина повідомлень. Така інфраструктура як правило не містить доменної логіки — прості реалізації типу RabbitMQ або ZeroMQ не роблять нічого крім надання асинхронної фабрики. Логіка при цьому існує на кінцях цієї шини — в сервісах, які відправляють і приймають повідомлення.

В монолітному додатку компоненти працюють в одному процесі і комунікують між собою через виклик методів. Найбільша проблема у зміні моноліту на микросервисы лежить у зміні шаблону комунікації. Наївне портування один до одного призводить до «балакучим» комунікацій, які працюють не надто добре. Замість цього ви повинні зменшити кількість комунікацій між модулями.

Децентралізоване управління
Одним з наслідків централізованого управління є тенденція до стандартизації використовуваних платформ. Досвід показує, що такий підхід занадто сильно обмежує вибір — не всяка проблема є окрасою і не всяке рішення є молотком. Ми воліємо використовувати правильний інструмент для кожної конкретної роботи. І хоча монолітні програми теж в деяких випадках можуть бути написані з використанням різних мов, це не є стандартною практикою.

Розбиваючи моноліт на сервіси, ми маємо вибір, як побудувати кожен з них. Хочете використовувати Node.js для простих сторінок з звітами? Будь ласка. C++ для real-time програм? Відмінно. Хочете замінити БД на ту, яка краще підходить для операцій читання вашого компонента? Заради бога.

Звичайно, тільки тому що ви можете робити що-то, не означає, що ви повинні це робити. Але розбиття системи подібним чином дає вам можливість вибору.

Команди, які розробляють микросервисы, також воліють інший підхід до стандартизації. Замість того, щоб використовувати набір визначених стандартів, написаних кимось, вони воліють ідею побудови корисних інструментів, які інші девелопери можуть використовувати для вирішення схожих проблем. Ці інструменти як правило вичленовані з коду одного з проектів та расшарены між різними командами, іноді використовуючи при цьому модель внутрішнього опен-сорса. Тепер, коли git і github стали де-факто стандартною системою контролю версій, опен-сорсные практики стають все більш і більш популярними у внутрішніх проектах компаній.

Netflix — хороший приклад організації, яка випливає цієї філософії. Расшаріваніє корисного і, більш того, протестованого на бойових серверах коду у вигляді бібліотек спонукає інших розробників вирішувати схожі проблеми схожим шляхом, залишаючи тим не менш можливість вибору іншого підходу при необхідності. Загальні бібліотеки мають тенденцію бути більш сфокусованими на загальних проблемах, пов'язаних із зберіганням даних, межпроцессорным взаємодією і автоматизацією інфраструктури.

Ком'юніті микросервисов цінує сервісні контракти, але не любить оверхеды і тому використовує різні шляхи управління цими контрактами. Такі шаблони Tolerant Reader і Consumer-Driven Contracts часто використовуються в микросервисах, що дозволяє їм розвиватися незалежно. Перевірка Consumer-Driven контрактів як частина білду збільшує впевненість у правильності функціонування сервісів. Ми знаємо команду з Австралії, яка використовує цей підхід для перевірки контрактів. Це стало частиною процесу їх складання: сервіс збирається тільки до того моменту, який задовольняє вимогам контракту — елегантний спосіб обійти, YAGNI.

Мабуть найвища точка в практиці децентралізованого управління — це метод, популизированный Амазоном. Команди відповідають за всі аспекти, що вони розробляють, включаючи підтримку в режимі 24/7. Подібна деволюція рівня відповідальності абсолютно точно не є нормою, але ми бачимо все більше і більше компаній, що передає відповідальність командам розробників. Netflix — ще одна компанія, практикуюча це. Пробудження в 3 години ночі — дуже сильний стимул до того, щоб приділяти велику увагу якості написаного коду.

Микросервисы і SOA
Коли ми розмовляємо про микросервисах, зазвичай виникає питання про те, чи це не є звичайним Service Oriented Architecture (SOA), який ми бачили десять років тому. В цьому питанні є здорове зерно, т. к. стиль микросервисов дуже схожий на те, що просувають деякі прихильники SOA. Проблема, проте, у тому, що термін SOA має сликом багато різних значень і, як правило, те, що люди називають «SOA» істотно відрізняється від стилю, описаного тут, зазвичай із-за надмірного фокусу на ESB, використовуваному для інтеграції монолітних додатків.

Зокрема, ми бачили так багато невдалих реалізацій SOA (починаючи з тенденції ховати складність через ESB, закінчуючи проваленими инциативами тривалістю кілька років, які коштували мільйони доларів і не принесли ніякої користі), що деколи дуже складно абстрагуватися від цих проблем.

Безумовно, багато практики, використовувані в микросервисах, прийшли з досвіду інтеграції сервісів у великих організаціях. Шаблон Tolerant Reader — один з прикладів. Інший приклад — використання простих протоколів — виник як реакція на централізовані стандарти, складність яких просто захоплює дух.

Ці проблеми SOA призвели до того, що деякі прихильники микросервисов відмовляються від терміна «SOA», хоча інші вважають микросервисы однією з форм SOA, або, можливо, правильною реалізацією SOA. У будь-якому разі, той факт, що SOA має різні значення, означає, що корисно мати окремий термін для позначення цього архітектурного стилю.

Безліч мов, безліч можливостей
Зростання платформи JVM — один з останніх прикладів змішування мов в рамках єдиної платформи. Перехід до більш високорівневих мов для одержання переваг, пов'язаних із використанням високорівневих абстракцій, був поширеною практикою протягом десятиліть. Точно так само, як і перехід «до залізу» для написання високопродуктивного коду.

Тим не менше, багато монолітних додатків не вимагають такого рівня оптимізації продуктивності і високорівневих можливостей DSL-подібних мов. Замість цього, моноліти як правило використовують єдину мову і схильні до обмеження кількості використовуваних технологій.

Децентралізоване управління даними
Децентралізоване управління даними постає в різному вигляді. В найбільш абстрактному розумінні це означає, що концептуальна модель світу у різних систем буде відрізнятися. Це звичайна проблема, що виникає при інтеграції різних частин великих enterprise-додатків: точка зору на поняття «Клієнт» у продавців буде відрізнятися від такої команди техпідтримки. Деякі атрибути «Клієнта» можуть бути присутніми в контексті продавців і відсутні в контексті техпідтримки. Більш того, атрибути з однаковою назвою можуть мати різне значення.

Ця проблема зустрічається не тільки у різних додатків, але також і в рамках єдиного додатка, особливо в тих випадках коли це додаток розділене на окремі компоненти. Цю проблему добре вирішує поняття Bounded Context з Domain-Driven Design (DDD). DDD пропонує ділити складну предметну область на кілька контекстів і мапить відносини між ними. Цей процес корисний як для монолітної, так і для микросервисной архітектур, але між сервісами і контекстами існує природна зв'язок, яка допомагає прояснювати і підтримувати межі контекстів.

Крім децентралізації прийняття рішень про моделюванні предметної області, микросервисы також сприяють децентралізації способів зберігання даних. У той час як монолітні додатки схильні до використання єдиною БД для зберігання даних, компанії часто воліють використовувати єдину БД для цілого набору додатків. Такі рішення, як правило, викликані моделлю ліцензування баз даних. Микросервисы воліють давати можливість кожному сервісу керувати власною базою даних: як створювати окремі инстансы загальною для компанії СУБД, так і використовувати нестандартні види баз даних. Цей підхід називається Polyglot Persistence. Ви також можете застосовувати Polyglot Persistence в монолітних додатках, але в микросервисах такий підхід зустрічається частіше.

image

Децентралізація відповідальності за дані серед микросервисов надає вплив на те, як ці дані змінюються. Звичайний підхід до зміни даних полягає у використанні транзакцій для гарантування консистентности при зміні даних, що знаходяться на кількох ресурсах. Такий підхід часто використовується в монолітних додатках.

Подібне використання транзакцій гарантує консистентним, але призводить до істотної временной залежності (temporal coupling), яка, в свою чергу, призводить до проблемамм при роботі з безліччю сервісів. Розподілені транзакції неймовірно складні в реалізації і, як наслідок, микросервисная архітектура надає особливого значення координації між сервісами без використання транзакцій з явним позначенням того, що консистентним може бути тільки підсумкової (eventual consistency) і виникаючі проблеми вирішуються операціями компенсації.

Управління неузгодженостями подібним чином — новий виклик для багатьох команд розробки, але це часто відповідає практик бізнесу. Часто компанії прагнуть як можна швидше реагувати на дії користувача і мають процеси, позвояющие скасувати дії користувачів у разі помилки. Компроміс варто того до тих пір, поки вартість виправлення помилки менше вартості втрат бізнесу при використанні сценаріїв, що гарантують консистентним.

Стандартні, перевірені в бою, vs нав'язані стандарти
Команди, що використовують микросервисную архітектуру, схильні уникати жорстких стандартів, встановлених групами системних архітекторів. Вони також схильні використовувати і навіть просувати відкриті стандарти типу HTTP і ATOM.

Ключова відмінність у тому, як ці стандарти розробляються та як вони проводяться в життя. Стандарти, керовані групами начебто IETF, стають стандартами тільки тоді, коли знаходяться декілька реалізацій в успішних open-source проектах.

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

Автоматизація інфраструктури
Техніки автоматизації інфраструктури сильно еволюціонували за останні кілька років. Еволюція хмари в цілому і AWS зокрема зменшила операційну складність побудови, розгортання і функціонування микросервисов.

Безліч продуктів і систем, що використовують микросервисную архітектуру, були побудовані командами з великим досвідом у Continuous Delivery і Continuous Integration. Команди, які будують додатки подобнымм чином, інтенсивно використовують техніки автоматизації інфраструктури. Це проілюстровано на малюнку нижче.

image

Так як ця стаття не про Continuous Delivery, ми приділимо увагу лише парі його ключових моментів. Ми хочемо отримувати якомога більше впевненості в тому, що наш додаток працює, тому ми запускаємо безліч автоматичних тестів. Для виконання кожного кроку автоматичного тестування додаток розгортається в окремій середовищі, для чого використовується автоматичного розгортання (automated deployment).

Після того як ви інвестували гроші в автоматизацію процесу розгортання моноліту, розгортання більшої кількості програм (сервісів) вже не видається таким страшним. Згадаєте, що одна з цілей Continuous Delivery — це зробити розгортання нудним, так що одне це додаток або три не має великого значення.

Інша область, де команди використовують інтенсивну автоматизацію інфраструктури, — це управління микросервисами в продакшне. На відміну від процесу розгортання, який, як описано вище, у монолітних додатків не сильно відрізняється від такого у микросервисов, їх спосіб фунционирования може істотно відрізнятися.

image

Одним з побічних ефектів автоматизації процесу розгортання є створення зручних інструментів для допомоги розробникам і адміністраторам (operations folk). Інструменти для управління кодом, розгортання простих сервісів моніторингу та логування зараз досить поширені. Можливо найкращий приклад, який можна знайти в мережі, — це набір open source інструментів від Netflix, але існують і інші, наприклад Dropwizard, який ми досить інтенсивно використовуємо.

Проектування під відмова (Design for failure)
Наслідком використання сервісів як компонентів є необхідність проектування додатків так, щоб вони могли працювати при відмові окремих сервісів. Будь-яке звернення до сервісу може не спрацювати через його недоступність. Клієнт повинен реагувати на це настільки терпимо, наскільки можливо. Це є недоліком микросервисов порівняно з монолітом, т. к. це вносить додаткову складність в додаток. Як наслідок, команди микросервисов постійно думають тим, як недоступність сервісів повинна впливати на user experience. Simian Army від Netflix штучно викликає (симулює) відмови сервісів і навіть датацентрів протягом робочого дня для тестування відмовостійкості програми та служб моніторингу.

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

Так як сервіси можуть відмовити в будь-який час, дуже важливо мати змогу швидко виявити неполадки і, якщо можливо, автоматично відновити працездатність сервісу. Микросервисная архітектура робить великий акцент на моніторингу програми в режимі реального часу, перевірці як технічних елементів (наприклад, як багато запитів у секунду отримує база даних), так і бізнес-метрик (наприклад, як багато замовлень на хвилину отримує додаток). Семантичний моніторинг може надати систему раннього попередження проблемних ситуацій, дозволяючи команді розробці підключитися до дослідження проблеми на ранніх стадіях.

Це особливо важливо випадку з микросервисной архітектурою, т. к. розбиття на окремі процеси і комунікація через події приводить до несподіваного поведінки. Моніторинг вкрай важливий для виявлення небажаних випадків такої поведінки і швидкого їх усунення.

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

Команди микросервисов, як правило, створюють витончені системи моніторингу та логування для кожного індивідуального сервісу. Прикладом може служити консоль, що показує статус (онлайн/офлайн) сервісу і різні технічні та бізнес-метрики: поточна пропускна здатність, час обробки запиту і т. п.

Синхронні виклики вважаються небезпечними
Кожен раз, коли ви маєте набір синхронних викликів між сервісами, ви стикаєтеся з ефектом мультиплікації часу простою (downtime). Час простою вашої системи стає твором часу простою індивідуальних компонент системи. Ви постаєте перед вибором: або зробити ваші виклики асинхронними, або миритися з простоями. Наприклад, в www.guardian.co.uk розробники ввели просте правило — один синхронний виклик на один запит користувача. Netflix ж взагалі все API є асинхронними.

Еволюційний дизайн
Ті, хто практикує микросервисную архітектуру, зазвичай багато працювали з еволюційним дизайном і розглядають декомпозицію сервісів як подальшу можливість дати розробникам контроль над змінами (рефакторінгом) їх застосування без уповільнення самого процесу розробки. Контроль над змінами не обов'язково означає зменшення змін: з правильним підходом і набором інструментів можна робити часті, швидкі, добре контрольовані зміни.

Кожен раз, коли ви намагаєтеся розбити програму на компоненти, ви стикаєтеся з необхідністю прийняти рішення, як саме ділити додаток. Чи є якісь принципи, які вказують, як найкращим способом «нарізати» наше додаток? Ключове властивість компонента — це незалежність його заміни або оновлення, що передбачає наявність ситуацій коли його можна переписати з нуля без підняття взаємодіючих з ним компонентів. Багато команд розробників йдуть ще далі: вони явним чином планують, що безліч сервісів в довгостроковій перспективі не буде еволюціонувати, а будуть просто викинуті на смітник.

Веб-сайт Guardian — хороший приклад програми, яке було спроектовано і побудовано як моноліт, але потім еволюціонувало в бік микросервисов. Ядро сайту все ще залишається монолітом, але нові фічі додаються шляхом побудови микросервисов, які використовують API моноліту. Такий підхід особливо корисний для функціональності, яка по суті своїй є тимчасовою. Приклад такої функціональності — спеціалізовані сторінки для висвітлення спортивних подій. Такі частині сайту, можуть бути швидко зібрані разом з використанням швидких мов програмування і видалені як тільки закінчиться подія. Ми бачили схожий підхід у фінансових системах, де нові сервіси додавалися під відкриті ринкові можливості і видаляється через кілька місяців або навіть тижнів після створення.

Такий наголос на заменяемости — окремий випадок більш загального принципу модульного дизайну, який полягає в тому, що модульність визначається швидкістю зміни функціоналу. Речі, які змінюються разом, повинні зберігатися в одному модулі. Частини системи, що змінюються рідко, не повинні знаходитися разом з быстроэволюционирующими сервісами. Якщо ви регулярно міняєте два сервісу разом, задумайтеся над тим, що можливо їх слід об'єднати.

Приміщення компонент сервіси додає можливість більш точного (granular) планування релізу. З монолітом будь-які зміни вимагають перезбирання і розгортання всього програми. З микросервисами вам потрібно розгорнути (redeploy) тільки ті сервіси, що змінилися. Це дозволяє спростити і прискорити процес релізу. Недолік такого підходу в тому, що вам доводиться хвилюватися щодо того, що зміни в одному сервісі зламають сервіси, які звертаються до нього. Традиційний підхід до інтеграції полягає в тому, щоб вирішувати такі проблеми шляхом версійності, але микросервисы воліють використовувати версійність тільки у випадку крайньої необхідності. Ми можемо уникнути версійності шляхом проектування сервісів так, щоб вони були настільки толерантні до змін сусідніх сервісів, наскільки можливо.

За микросервисами майбутнє?

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

Відомі нам піонери цього архітектурного стилю — це такі компанії, як Amazon, Netflix, The Guardian, the UK Government Digital Service, realestate.com.au, Forward і comparethemarket.com. Конференції 2013 року були сповнені прикладів команії, які рухаються у напрямку, який можна класифікувати як микросервисы, наприклад, Travis CI. До того ж, існує безліч організацій, які вже давно використовують те, що ми називаємо микросервисами, але не використовують цю назву. (Часто це називається SOA, хоча, як ми вже говорили, SOA може бути в самих різних і часто суперечливих формах.)

Незважаючи на весь цей позитивний досвід, ми не стверджуємо, що микросервисы — це майбутнє проектування ПО. І хоча наш досвід поки що вельми позитивний порівняно з досвідом використання монолітної архітектури, ми підходимо усвідомлено до того факту, що пройшло ще недостатньо часу для того, щоб виносити таке судження.

Часто справжні наслідки ваших архітектурних рішень стають видно тільки через кілька років після того, як ви зробили їх. Ми бачили проекти, в яких хороші команди з сильним прагненням до модульності розробили монолітні додатки, повністю «прогнилі» по закінченню декількох років. Багато хто вважає, що такий результат менш імовірний у випадку з микросервисами, т. к. кордону між сервісами є фізичними та їх складно порушити. Тим не менше, до тих поки ми не побачимо достатньої кількості перевірених часом систем, що використовують цей підхід, ми не можемо з упевненістю стверджувати, наскільки микросервисная архітектура є зрілою.

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

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

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

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

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

Посилання на оригінал статті: Microservices

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.