.NET Fest: полная программа конференции на сайте. Присоединяйся к самому большому .NET ивенту
×Закрыть

Складнощі тестування мікросервісів та що з ними робити

У червні 2019 року я виступив на конференції ProQA.Today на тему тестування мікросервісів. Якщо коротко, то в моїй доповіді було чимало критики й могло скластися враження, що я затятий противник технології, але це не так — удома я навіть маю свій Docker Registry на окремому сервері, з багатьма контейнерами для різних тестерських експериментів. А в Google Cloud у мене є власний застосунок. Як і в будь-якій технології, я бачу в мікросервісах сильні і слабкі сторони, де чимало залежить від правильної архітектури й способу використання. Кілька місяців я обмірковував свою доповідь, виступи інших спікерів та критику й готовий структурувати свої думки у статтю. Усі приклади нижче — мій досвід тестування монолітних систем і мікросервісів.

Точка відліку

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

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

Що мені не подобається в тестуванні мікросервісів

Мікросервіси складно тестувати атомарно. У 99% випадків не можна запустити один окремий мікросервіс, щоб протестувати його REST веб-сервіси, наприклад, не створивши спочатку мок усіх пов’язаних з ним сервісів. Якщо в команди розробки немає часу робити моки, можна забути про інтеграційне тестування на умовному Jenkins’і у вакуумі. Уже тут мене запитують: а як же тестування контрактів? Як я розумію, тестування контрактів лише перевіряє відповідність веб-сервісів специфікації (swagger чи щось подібне), а мене цікавить саме тестування веб-сервісів з визначеними сетами даних. З монолітами зазвичай простіше — хоч локально розгорни собі систему й тестуй.

Для мікросервісів важко керувати даними. Кожен мікросервіс може мати свою окрему базу даних, ніяк не пов’язану з базами інших мікросервісів. З погляду автономності це, звісно, правильно, але є одне «але»: якщо сутності (об’єкти) в системі, що ми тестуємо, складаються з менших сутностей кожного мікросервісу (як Вольтрон), база даних не може забезпечити їхньої цілісності. Для зв’язності даних у кожному мікросервісі потрібно створювати окремий механізм, наприклад, зберігати ID сутностей інших сервісів. Проблема в тому, що дані одного мікросервісу можна стерти й помилку можна знайти лише на етапі тестування (або в продакшені). А під час створення/заміни даних потрібно запам’ятовувати ID одних об’єктів, щоб потім зберегти їх у базах інших мікросервісів. Єдиним робочим підходом нашої команди стало створення й редагування даних через UI в невеликих обсягах під кожний конкретний тест — так довше, ніж прямо через БД, але простіше.

Для мікросервісів важко забезпечити транзакційність. Тут як у поганому анекдоті: «Студент, щоб скласти сесію, дав хабаря викладачеві, потім секретарю декана, а потім декан хабаря не взяв. Жаль, що хабарі не транзакційні й перші двоє грошей не повернуть». Тестування транзакцій у мікросервісах подібне до цього жарту: перший сервіс робить зміни в даних і передає їх другому сервісу — другий сервіс робить зміни у своїх даних і передає третьому, і тут трапляється помилка! Не просто помилка, а наприклад, необроблений Null Pointer Exception. Тест не пройшов, дані перших двох мікросервісів не відповідають іншим — потрібно вручну їх чистити. Ба більше, для забезпечення транзакційності між різними мікросервісами розробникам треба писати більше коду, більше веб-сервісів для зворотного зв’язку (що потребує більше часу на тестування). А найгірше те, що з погляду цілої системи може бути зовсім не очевидно, в якому саме мікросервісі сталася помилка — потрібно брати логи й дані всіх залучених сервісів і перевіряти. У монолітах транзакційність часто гарантують на рівні БД.

Мікросервіси можуть використовувати різні канали зв’язку. Коли розпочинають розробку нової системи, кожен розробник мріє про простий уніфікований інтерфейс. Наразі дуже популярний, наприклад, REST. «Нехай усі наші мікросервіси взаємодіятимуть тільки через REST, казали вони...» Проте під час розробки щоразу трапляються ситуації:

  • цей 3rd-party-мікросервіс взаємодіє лише через SOAP, ми не можемо нічого вдіяти, під’єднуватимемо, як є;
  • для реалізації цієї фічі потрібно передавати інформацію декільком мікросервісам одночасно й асинхронно — скористаймося JMS, це просто й надійно;
  • у нас тут є legacy-система, вона працює лише через свій власний протокол на базі TCP;
  • нам потрібно гарантувати синхронізацію «дуже важливих даних»™, тому нехай перший сервіс писатиме дані в окрему базу, а інший сервіс раз на хвилину їх вичитуватиме.

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

Для системи мікросервісів важко зробити автоматизоване UI-тестування. Насправді розробити самі автотести легко, і той же Selenium WebDriver добре виконує свою роботу. Проблеми з’являються, коли ми намагаємося додати автотести в CI/CD. З монолітом усе просто:

  1. Новий білд.
  2. Автотести.
  3. ???
  4. Profit.

Складнощі починаються, коли система складається з 2+ мікросервісів:

Q: Де виконувати регресійні тести?
A: На умовному Jenkins потрібно створити велику кількість моків.
Q: Може, після деплою?
А: А якщо під час виконання тесту почнеться деплой іншого мікросервісу?
Q: Ставити всі білди в чергу?
А: А якщо черга стане завелика?

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

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

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

Кожен веб-сервіс одночасно повинен передавати більше даних, бо буває, що перший мікросервіс передає дані другому, той використовує два умовні поля для своїх обрахунків (наприклад, лише перевіряє ID), а всі інші дані передає наступному сервісу, якому вони корисні (на рисунку схема передачі корисного навантаження payload між мікросервісами. Поля, що використовує сервіс — підсвічено).

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

У мікросервісах важче знайти першопричину помилки. Базова інструкція тестувальника вимагає, що в разі знаходження бага потрібно його відтворити й зарепортити з усіма передумовами, кроками, сподіваними результатами тощо. Однак кожний тестувальник знає, що в разі складних систем для успішного фіксу, краще знайти першопричину бага, додати логи й дані, щоб не отримати cannot reproduce. І в мікросервісах це може стати справжньою проблемою, якщо одна дія користувача спричинює ланцюгову реакцію, де залучено чимало систем. У якому сервісі помилка?

Помилка виникла через баг у коді мікросервісу чи через те, що інший сервіс передав йому неправильні дані? А може, помилки в коді взагалі немає, просто операція завершилася за timeout, і проблема в інфраструктурі? Ще гірше, якщо баг виникає в проді, до бази й логів якого команда не має доступу через GDPR. Поради, що робити, немає — тут рятує лише відмінне знання командою системи й можливість припустити причину з великою ймовірністю.

Мікросервіси потребують чимало ресурсів. Я пам’ятаю ті часи, коли мав низку невеликих тестових серверів на Tomcat з кількома гігабайтами RAM, у які міг сам задеплоїти нову версію продукту й почати тестування. Навіть робити редеплой попередніх версій, щоб визначити, коли саме з’явилася помилка. Нині середовище тестування системи мікросервісів, в якому я працюю, потребує 64 ГБ. А іноді й цього замало! Я не сказав би, що інфраструктура — це безпосередня проблема тест-ліда, але коли в системі ліміт ресурсів, то це може спричинити баги й неможливість вчасно додати ще один контейнер з тестами. Кожен контейнер мікросервісу — власна віртуальна машина, що використовує ресурси, у разі ж моноліту (який теж можна запакувати в докер за потреби) — у нас є лише один сервер чи віртуальна машина.

Висновки

Тепер спробую позитивно підсумувати все вище написане :) Я не закликаю відмовлятися від мікросервісів — лише бути готовим до складнощів, які ця технологія може спричинити, зокрема:

  • Вимагати якомога більше прав для роботи із середовищем — консольні утиліти для отримання логів і під’єднання до контейнера можуть значно спростити життя.
  • Вимагати зберігати всю критичну інформацію контейнерів (логи, файли) в постійному сховищі (база даних, FTP, спільна тека), бо в разі крешу контейнера чи деплою нової версії мікросервісу, дані можуть бути втрачені.
  • Ознайомитися з докером (що це, як працює) і командами оркестраторів типу Kubernetes, Openshift (вони майже ідентичні).
  • Не створювати багато тестових даних заздалегідь — вони швидко втрачають актуальність.
  • Постійно вивчати розроблену систему не лише за вимогами, а й з погляду архітектури — так буде легше розуміти, що й де може піти не так.
  • Обов’язково тестувати навантаження, щоб виявити вузькі місця й баги синхронізації.
  • Вивчити хоча б одну мову програмування — невеликі скрипти можуть значно полегшити вашу роботу.

Дякую, що дочитали. Напишіть про ваш досвід, мені справді цікаво знати success story :)

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

LinkedIn

Лучшие комментарии пропустить

Как надоели 23 летние «иксперды». Хотя написание статьи уже труд и шаг вперед 😊 . Вопросы показывают «грабли» по которым прошелся автор, поэтому разбираем шаг за шагом:

1 «У 99% випадків не можна запустити один окремий мікросервіс,» — вы создали не микросервис а странное существо, разбейте «микросервис» на «микро» и «сервис» и посмотрите на определение сервиса как такового.

2 «Для мікросервісів важко керувати даними. Кожен мікросервіс може мати свою окрему базу даних» — для начала см. п. 1, далее рассматривать неправильно примененный аспект не есть хорошо. Интеграция сервисов многогранна и возможно Вы выбрали не совсем корректный путь. Интерграция может быть : файлы, локальная база., глобальная база, визуальная интреграция ( если приминимо),сервисы — Web Services, RMI, COM, DCOM, Net remoting, EJB, сообщения — JMS, MSMQ, AMPQ, почта, IPC — named pipes, shared memory, ESB, Etc

3 «Для мікросервісів важко забезпечити транзакційність. » — да/нет, см пункт 2 . Паттерны в помощь — двухфазные комиты и caga. Ну и зависит от того как Вы базу используете.

4 «Мікросервіси можуть використовувати різні канали зв’язку. Коли» — хозяин — барин. Выбирайте то, что выгоднее.

5 «Для системи мікросервісів важко зробити автоматизоване UI-тестування.» — норм. 3 года назад полнностью разворачивали ui тестирование как часть ci/cd процесса. Может поможет — dzone.com/...​ntainerised-microservices часть вопросов покрыта ответами.

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

В добавок
1 Тут в нашей «галере» кто-то ратует за нано сервисы ... ну далее сами знаете
2 Не ругают того, кого не желают видеть лучше

Вся аргументация притянута за уши. При условии что архитектура разрабатывалась не имбецилами никаких проблем с тестированием микросервисов нет и быть не может. Особенно доставило «Для мікросервісів важко забезпечити транзакційність» — what? Походу нет вообще базового понимания что микросервисная архитектура не про это а про eventual consistency. Но все равно в тех исключительных случаях когда действительно надо транзакции распределенные по нескольким сервисам за тебя уже давно придумали механизм саги.

Микросервисы очень хорошо тестируются атомарно.

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

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

Разные средства коммунации между сервисами: но ведь и в монолите могут быть разные типы апи, которые так же надо тестировать. И тоже — изучать надо много инструментов.

Для микросервисов вполне можно делать UI тестирование — как системы целиком. Нужно только иметь самые важные кейсы на этом уровне. И если сервис покрыт тестами хорошо на нижних уровнях — то много автотестов на верхнем уровне при деплое сервиса не нужно. (Особенно если изменение деплоится в hidden mode). Отдельно можно заморочиться с Test Impact Analysis (автоматически или вручную) и запускать ровно те UI тесты, на которые влияет конкретный сервис.

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

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

101 комментарий

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.
Тестування транзакцій у мікросервісах подібне до цього жарту: перший сервіс робить зміни в даних і передає їх другому сервісу — другий сервіс робить зміни у своїх даних і передає третьому, і тут трапляється помилка! Не просто помилка, а наприклад, необроблений Null Pointer Exception. Тест не пройшов, дані перших двох мікросервісів не відповідають іншим

вот только юмор в том, что это тогда вообще не микросервисы, а самый наглядный пример монолита

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

и это неверно

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

Взагалі ускладнення інфраструктури мікросервісів змінило підхід до програмування — люди звикли писати так, щоб не переписувати. Одразу вирішуємо гіпотетичні проблеми наперед.

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

Как быда, но это если пишущие понимают, что такое soaархитектура вообще и микросервисы в частности.

Мікросервіси складно тестувати атомарно. У 99% випадків не можна запустити один окремий мікросервіс, щоб протестувати його REST веб-сервіси, наприклад, не створивши спочатку мок усіх пов’язаних з ним сервісів.

это просто означает что ваши «сервисы» совсем не «микро» да и сама архитектура несколько сомнительно запутана и overcomplicated если 99% «микросервисов» зависят и взаимодействуют с таким числом других микросервисов а взаимодействия в свою очередь настолько сложны что их трудно закрыть простыми а то и вообще автоматическим скриптом сгенерированными моками и даже стабами

ЗЫ: кстати на «монолите» наблюдаются ровно те же ж трагетии только уже с юнит-тестированием когда таки да «монолит» тупо не делится на «юниты» которые хоть как-то запускались бы б и тем более работали бы б отдельно ))

нарешті маю час на коменти трошки відповісти і нового щось дізнатись

«сервисы» совсем не «микро»

1 мікросервіс — 1 бізнес задача. Деякі бізнес задачі можуть будти комплексні та не ділитись. чи є критерії, коли сервіс вже не мікро?

99% «микросервисов» зависят и взаимодействуют с таким числом других микросервисов

ви читаєте не те, що написано:

не можна запустити один окремий мікросервіс, щоб протестувати його REST веб-сервіси, наприклад, не створивши спочатку мок усіх пов’язаних з ним сервісів

«усіх» може бути 1,2. А може й N-1

на «монолите» наблюдаются ровно те же ж трагетии

дійсно так може бути — якщо код і архітектура лайно, то погано працює і в моноліті, і в мікросервісах

Не ображайся, але твоя стаття це «Горе від розуму», почитай книги про мікро сервіси та патерни xUnit тестування, а також про Docker + testcontainers
А ще дуже дивно, як ПК ProQA конфи пропустили таку доповідь на конференцію...

Горе від розуму

кожного дня страждаю ;)

патерни xUnit тестування, а також про Docker + testcontainers

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

дивно, як ПК ProQA конфи пропустили таку доповідь

сам в шоці

Микросервисы. Паттерны разработки и рефакторинга. Крис Ричардсон — перша книга з результатів пошуку «микросервіси книга»
Паттерны тестирования xUnit — Мисарош. Має багато корисних порад як тестувати із моками, як пимати не залежні та атомарні тести
Docker ну камон, доки в нього вогонь

Ну а так дуже важливо розуміти що мікросервіси тестувати значно легше ніж UI, але потрібно вміти в код — без цього ніяк ти ефективно не покриєш функціонал та інтеграцію мікросервісів.
Раджу ще знайти статті як тестують в Spotify та в Pinterest.
Всі проблеми з якими ти стикнувся насправді просто із-за не знання мов програмування, в чому переваги мікросервісів в порівнянні із монолітом (особливо в плані тестування — а тестування мікросервісів це тільки автоматизація), також як білдити мікросервіси та піднімати їх на кожен коміт в докері чі через кубер, ну і відповідно як то тримати суто в коді — тобі тоді і енв не потрібен буде.
Ібо в розробці сучасних додатків все крутиться в докері та підняти оточення зараз дуже дешево. Наприклад запустити тести на мікросервіси в blueocean які пробіжать за 3 хвилини на овер 10 ядрах та овер 20 оперативки буде коштувати як випити чашку кави в MacDonald’s. І то буде відповідно до оточення. Для оточення зробити окремі e2e тести які будуть бігати на кожен дєплой мікросервісів. Також прикрутити elk для зручної обробки догів
Все це робиться через програмування

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

Мікросервіси це зручно, не просто звісно але ціна автоматизації значно менша ніж руцями тикати постмен тільки на «реальному» оточенні

Если еще нужны материалы — советую начинать с habr.com/...​y/oleg-bunin/blog/349632 .
Дальше тоже про подходы: www.infoq.com/...​ques-microservices-intro

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

Как пример — у нас тестирование происходит без лишних вопросов и в 1 заход, — потому как разрабатываем на высшем уровне качества в короткое время

взоржал

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

тут нет твоих клиентов — можешь расслабиться

Расслабляться Ваша хамская прерогатива. К сожалению, и такие рабы есть...
Знаю таких рабов... Они абсолютно не думают что с ними будет, и что владельцы бизнеса держат хамов на карандаше и общаются между собой :) ... (буквально недавно такие уволенные просились обратно) А с октября я объявляю набор на новые интересные проекты. основа: полная свобода и зп в 3 раза больше чем текущая...

Я бы в принципе не работал с менеджером, архитектом, который людей считает за рабов.

конечно компании и команды бывают разные.

но...
у меня с одним субподрядчиком, на старте, состоялся кратко такой диалог, когда выставлял им требования по интеграции:
— ...если наш сервис выдаст вам 4**такую, то, вы должны повторить попытку записи, через 10 сек...
— а можно чтобы он не выдавал такую ошибку, а всегда принимал ответ?
— ммм... можно... (и решил отшутиться, чтобы долго не объяснять причину), но мы не умеем писать надежное ПО
— а мы умеем! и бла-бла-бла,
типа вашего ...

хорошие кстати субподрядчики.

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

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

не надо путать ЦА, с «а мы умеем писать надежное ПО которое не падает!» :)

ну, Ок... Каждый остается при своем... Я выстраиваю бизнес на сбалансированной скорости, цене, качестве. И самое главное — я абсолютно прозрачен (вплоть до «где вы и сколько зарабатываете») и честен (где, как и когда может упасть, что может вызвать всплеск)
И возвращаясь к вопросу тестирования — качественно созданные микросервисы не требуют вопросов у тестировщиков...

кому интересно как вы выстраиваете свой бизнес
если вы не в состоянии услышать то что вам говорят :D

с Вами точно нет никакого желания... И рекомендации на рынке ИТ я уже отписал... Говорите дальше...

И возвращаясь к вопросу тестирования — качественно созданные микросервисы не требуют вопросов у тестировщиков...

Чак, перелогинься

Как пример — у нас тестирование происходит без лишних вопросов и в 1 заход, — потому как разрабатываем на высшем уровне качества в короткое время

в чому ваш секрет, майстре? :)

«знал бы прикуп, — жил бы в Сочи»
мне бы хотелось, чтоб разработка, развитие и внедрение проходило во всех компаниях с умом.
в свое время я дотошно рассказывал на встречах БА и ПМ, и понял, что мало кто в это верит, пока не оказывается в моей команде... Так что — команда единомышленников и фанатов, которые делают общее дело — скорее всего это секрет. (нельзя делать дело с людьми, которым наплевать или не интересно на то, как живет компания, что нужно чтоб получать хороший доход со свободой. с теми, кто пришел, отработал с 9-ти до 18-ти и на все остальное начхать нельзя работать). Наша команда принимает сама решение о проектах, об ее участниках, о скорости, качестве и сумме вознаграждений, о наличии офиса и оборудования. Все работают как одно целое, — поэтому разработчики мотивированы писать код без помарок, аналитики писать документацию без лишних вопросов, а тестер еще до кода описывает кейсы и участвует в процессе не только на стадии тестирования.
наверное, такой будет ответ, не смотря на Вашу иронию с подергиванием.

Так всё-таки?..)

що з ними робити

Как надоели 23 летние «иксперды». Хотя написание статьи уже труд и шаг вперед 😊 . Вопросы показывают «грабли» по которым прошелся автор, поэтому разбираем шаг за шагом:

1 «У 99% випадків не можна запустити один окремий мікросервіс,» — вы создали не микросервис а странное существо, разбейте «микросервис» на «микро» и «сервис» и посмотрите на определение сервиса как такового.

2 «Для мікросервісів важко керувати даними. Кожен мікросервіс може мати свою окрему базу даних» — для начала см. п. 1, далее рассматривать неправильно примененный аспект не есть хорошо. Интеграция сервисов многогранна и возможно Вы выбрали не совсем корректный путь. Интерграция может быть : файлы, локальная база., глобальная база, визуальная интреграция ( если приминимо),сервисы — Web Services, RMI, COM, DCOM, Net remoting, EJB, сообщения — JMS, MSMQ, AMPQ, почта, IPC — named pipes, shared memory, ESB, Etc

3 «Для мікросервісів важко забезпечити транзакційність. » — да/нет, см пункт 2 . Паттерны в помощь — двухфазные комиты и caga. Ну и зависит от того как Вы базу используете.

4 «Мікросервіси можуть використовувати різні канали зв’язку. Коли» — хозяин — барин. Выбирайте то, что выгоднее.

5 «Для системи мікросервісів важко зробити автоматизоване UI-тестування.» — норм. 3 года назад полнностью разворачивали ui тестирование как часть ci/cd процесса. Может поможет — dzone.com/...​ntainerised-microservices часть вопросов покрыта ответами.

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

В добавок
1 Тут в нашей «галере» кто-то ратует за нано сервисы ... ну далее сами знаете
2 Не ругают того, кого не желают видеть лучше

двухфазные комиты

Спасибо, не нужно. Кстати, как закоммитить в кафку (любой друго брокер) и монгу (любая другая БД) в одной транзакции?

1. У Кафки нет брокера :) оперируем размером и интервалом 2. Аналогично любой БД 3. в одной транзакции — вставляем кафка размер в 1 и пуляем все в одной транзакции, сначала кафку.

1 иметься ввиду в понимании jms

Аналогично любой БД 3. в одной транзакции — вставляем кафка размер в 1 и пуляем все в одной транзакции, сначала кафку.

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

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

А если записали сообщение, но отвалились до того, как прочитали?

прочитали сообщение в другом месте / в другое время — записали .... что-то без контекста фигней страдаем

Веду к тому, что единственное вменяемое решение — это Outbox (или transaction log tailing для NoSql баз данных) паттерн и eventual consistency.

прочитали сообщение в другом месте / в другое время — записали

А клиент что в это время делает? В общем, да, ниочем.

Тогда не совсем понял что подразумевала ваша «одна транзакция»? явно не ACID транзакцию и не DDD команда изменения состояния агрегата.

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

интересный подход, дадите почитать какую-то литературу/paper по нему? это какой-то новый паттерн?

Martin Kleppmann об этом рассказывал, возможно, в этом видео www.youtube.com/watch?v=5ZjhNTM8XU8, но я не уверен. Дичь, в общем.

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

А, ну, и optimistic concurrency получить не получится. Короче такая себе идея.

Транзакции переоценены. Целостность можно достигать другими путями, делать это проще если еще и пойти по ever sourcing way.

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

Теперь к сути. Что за транзакция такая, которая может и в брокер писать и в бд? Максимум, что может быть — это транзакция самой кафки и транзакция бд, но это будут две разные транзакции, которые не умеют участвовать в Two Phase Commit. Т.е., если после коммита одной из транзакций отвалится или приложение, или координатор, или второй участник, система останется в неконсистентном состоянии.

:) и спрашивается , при чем тут двухфазный комит !?

Это из 3-го пункта отригинального сообщения, которое я прокомментировал 🙂

3 «Для мікросервісів важко забезпечити транзакційність. » — да/нет, см пункт 2 . Паттерны в помощь — двухфазные комиты и caga. Ну и зависит от того как Вы базу используете.

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

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

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

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

По транзакциям между разными БД (MS и Oracle, возможно и др БД поддерживают) использовал под .Net — Распределенные трансакции.
Проблем не припоминаю
docs.microsoft.com/...​/distributed-transactions

проблема в том, что это противоречит принципам микросервисов

Сорри, нет опыта разработки микросервисов. Учту.

поки десь тупив з відповідями, тут вже цілий тред намалювався :)

23 летние «иксперды»

дякую за теплі слова, аж зморшок менше стало на чолі. З вас, сподіваюсь, пісок ще не сиплеться ;)

Вопросы показывают «грабли» по которым прошелся автор

тут ви праві — я гарно влаштувався. Це лише мої граблі і на істину я не претендую

У 99% випадків не можна запустити один окремий мікросервіс

трохи вирвано з контексту, але буду більш обачний з формулюванням — запустити можна, а от перевірити працездатність без моків/стабів/інших сервісів — складно

2 «Для мікросервісів важко керувати даними...

тут я,ч есно скажу, не дуже зрозімів посил, почали за дані, закінчили інтеграцією. RMI, COM, DCOM — більше абревіатур зроблять коммент розумнішим ;) Хоча ви праві в тому, що підходи до даних є різні

3 «Для мікросервісів важко забезпечити транзакційність. » — да/нет, см пункт 2

так, дійсно, залежить від використання БД, але давайте не будемо вдавати, що проблем взагалі нема

4 «Мікросервіси можуть використовувати різні канали зв’язку. Коли» — хозяин — барин. Выбирайте то, что выгоднее.

Вибрали, а щастя не знайшли

Может поможет — dzone.com/...​ntainerised-microservices часть вопросов покрыта ответами.

дякую за посилання — почитаю обов’язково

1 Тут в нашей «галере» кто-то ратует за нано сервисы

саме цікаве питання, вже питав в коментатора вище — які критерії мікро сервіса? В моємо розумінні — 1 сервіс, одна бізнес задача/логічна одиниця. Чим мікро від нано відрізняється?

саме цікаве питання, вже питав в коментатора вище — які критерії мікро сервіса? В моємо розумінні — 1 сервіс, одна бізнес задача/логічна одиниця.

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

Чим мікро від нано відрізняється?

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

Это не издевка, а суровая реальность.

Мне больше с ромом коктейли нравятся или просто хороший ром.

Извините за «иксперды», бываю груб. П 2 — относительно известные пути интеграции приложений. Да, по поводу сервиса правильно со следующим дополнением — сервис это повторяющееся бизнес функция, которая не имеет состоятия в промежуток между транзакциям (бизнес). В крупную клетку отличаются — overhead, не надо оно Вам. И нет плохих инструментов, есть плохое применение.

Мікросервіси складно тестувати атомарно

в чому проблема підняти їх та тестувати на пряму ? це одна з переваг

Мікросервіси можуть використовувати різні канали зв’язку.

а в чому проблема використовувати різні канали зв’язку ? я певен, що є готові реалізації і для tcp і для RabbitMq і для будь чого іншого

власне, мікросервіси дають змогу легко спускатись на нижчі рівні тестування, а не тестувани все через UI чи API.

мікросервіси дають змогу легко спускатись на нижчі рівні тестування, а не тестувани все через UI чи API

А точно ли это нужно?

Да. Это правильно с точки зрения пирамиды тестов.

Уффф... Я не буду смотреть часовую лекцию, чтобы понять, что ты хотел мне сказать :)
Будь краток — и к тебе потянутся люди :)
Кроме того, пирамида тестов и TDD — это немножко разные вещи.

Я ссылкой поделился, куда уж короче 🙂.

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

А на примере CQRS unit — это или обрабока команды или обработка запроса со всеми внутренностями. Мокать стоит только внешние зависимости, как то отправка сообщений в брокер или вызовы API внешних сервисов.

А для бизнес локиги unit-тесты подходят отлично — там в идеале вообще ничего мокать не нудно так как логика предсказуема ввиду отсутвия IO. Это отсылка сюда blog.ploeh.dk/...​1/asynchronous-injection.

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

зіткнулись з такою проблемою. Тому більше націлені на тести на рівні сервісу

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

забавно что эти проблемы возникают у юнит тестов, которые не написаны по ТДД, писать тесты перед имплементацией как раз и помогает тестировать только контракт юнита

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

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

Суть в том, что классические Unit тесты в общем понимании ломаются при рефакторинге и замедляют разработку

Поэтому давайте вместо юнит тестов писать кучу UI тестов — пусть они ломаются ))))))
Только цена их поддержки в несколько раз выше, чем цена поддержки юнит тестов, а так да, идея неплохая ))))))

Бывает. Но все-таки рекомендую глянуть видео 😉.

це та, в якій треба привести двох друзів та стати золотим членом клубу? вибачте :)

Да, привести на проект 2-х друзей, которые знают, что это такое и не пытаются решить UI тестами все проблемы на проекте :)

А точно ли это нужно?

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

в чому проблема підняти їх та тестувати на пряму ? це одна з переваг

По-перше, моя думка — я не хочу тягнути з registry та запускати локально всі мікросервіси. Роблю і плачу
По-друге — вважаю, що тестування в готовому енвайрменті (production like) дає більш правдиві результати. Це як завести баг, а девелопер каже — на локальному білді в мене не репрод’юситься

а в чому проблема використовувати різні канали зв’язку ? я певен, що є готові реалізації і для tcp і для RabbitMq і для будь чого іншого

Синдром обманутих очікувань — спочатку всі кажуть, дивись, як классно ми все придумали, а по факту в мене на компі стоїть зоопарк всього + скрипти на пітоні для всіх типів коммунікації

власне, мікросервіси дають змогу легко спускатись на нижчі рівні тестування, а не тестувани все через UI чи API.

в вас ні разу не було такого, що unit, integration, api тести пройшли, а користувачы з продакшену баг заводять? Без UI тестів в складних системах ніяк

не хочу тягнути з registry та запускати локально всі мікросервіси. Роблю і плачу

угу. плачете, коли витрачаєте 10хв часу на тестування локально, але витрачаєте час на деплой, прогон повільних тестів і логування дефекту. Це буде точно довше ніж локальне тестування

вважаю, що тестування в готовому енвайрменті (production like) дає більш правдиві результати.
в вас ні разу не було такого, що unit, integration, api тести пройшли, а користувачы з продакшену баг заводять? Без UI тестів в складних системах ніяк

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

Как-то реклама тг канала не очень получилась. Где же про zipkin, elk для логов и прочее. И да, кодяру писать — это маст хев в 2019 году

Вся аргументация притянута за уши. При условии что архитектура разрабатывалась не имбецилами никаких проблем с тестированием микросервисов нет и быть не может. Особенно доставило «Для мікросервісів важко забезпечити транзакційність» — what? Походу нет вообще базового понимания что микросервисная архитектура не про это а про eventual consistency. Но все равно в тех исключительных случаях когда действительно надо транзакции распределенные по нескольким сервисам за тебя уже давно придумали механизм саги.

Согласен, проблемы автора детский лепет по сравнению с действительно серьезными проблемами. Например согласованность контрактов(что моделек для rest’a что ивентов в случае event sourcing) особенно когда у вас сервисов штук 30 и команд штук 10 которые параллельно девелопят=)

что ивентов в случае event sourcing

Ивенты в ES — это приватные ивенты. Из не нужно передавать в другие сервиый — это детали реализации контретного сервиса. Для общения между сервисами стоит использовать Integration Events.

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

у всіх своя біль — в нас з контрактами майже не було проблем за 3 роки розробки і вже N релізів в прод

Микросервисы очень хорошо тестируются атомарно.

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

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

Разные средства коммунации между сервисами: но ведь и в монолите могут быть разные типы апи, которые так же надо тестировать. И тоже — изучать надо много инструментов.

Для микросервисов вполне можно делать UI тестирование — как системы целиком. Нужно только иметь самые важные кейсы на этом уровне. И если сервис покрыт тестами хорошо на нижних уровнях — то много автотестов на верхнем уровне при деплое сервиса не нужно. (Особенно если изменение деплоится в hidden mode). Отдельно можно заморочиться с Test Impact Analysis (автоматически или вручную) и запускать ровно те UI тесты, на которые влияет конкретный сервис.

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

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

Для этого поднимается сам микросервис локально (может в контейнере), а все нужные зависимости (вроде баз данных или стриминга) — поднимаются тут же рядом в докер контейнерах

По-перше, моя думка — я не хочу тягнути з registry та запускати локально всі мікросервіси. Роблю і плачу
По-друге — вважаю, що тестування в готовому енвайрменті (production like) дає більш правдиві результати. Це як завести баг, а девелопер каже — на локальному білді в мене не репрод’юситься

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

навіть якщо не сильно зв’язані — все одно геморой

Разные средства коммунации между сервисами: но ведь и в монолите могут быть разные типы апи, которые так же надо тестировать. И тоже — изучать надо много инструментов.

імхо — зовсім різні рівні абстракції. В моноліті код викликає код, в мікросервісах код викликає умовний рест щоб викликати код в іншому сервісі. Ось вам аналогія: ви живете з сім’єю в квартирі, але замість спілкування напряму використовуєте пошту. Щоб спитати в дружини, чи купила вона суші на вечерю, ви пишете листа, надсилаєте та чекаєте на відповідь. А коли вам кажуть, що так не зручно, паруєте — зате універсально та добре масштабується на будь який розмір сім’ї

Нужно только иметь самые важные кейсы на этом уровне

про це і писав

імхо — зовсім різні рівні абстракції. В моноліті код викликає код, в мікросервісах код викликає умовний рест щоб викликати код в іншому сервісі.

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

аналогия с «семьёй» как раз годная просто вам надо делать не «семью» а завод ))

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

Теперь приходят QA и заявляют

не только они :)
хайп вокруг микросервисов пошел на спад, насколько могу судить с год-два

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

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

Зависит от размера монолита и количества команд же.

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

но главными аргументами ЗА микросервисы я бы назвал другие:
— необходимость в динамическом горизонтальном масштабировании
— «легкая» возможность обновления системы без ее полной остановки

тогда даже когда команда и в 5 человек, в одном офисе — надо выбирать микросервисный подход.
платить же на него придется, он не дешевле чем монолит — а дороже.

хайп же о том что микросервисы дешевле монолита

Правильный монолит тоже легко масштабировать горизонтально и деплоить без downtime 🙂.

конечно, бесспорно:
«Надо делать правильно! А неправильно — не надо делать.»

Нормально делай — нормально будет.

хайп вокруг микросервисов пошел на спад

одразу ж згадав — минулого року кожний другий проект намагався використати блокчейн — це ж круто, модно і за це платять більше

один из пунктов «за» микросервисы — это то, что их легче покрывать интеграционными

Можно ссыль, ни разу такого не встречал?

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

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

Это в теории :) но с теорией я согласен.

Теперь приходят QA и заявляют, что им неудобно тестировать микросервисы :)

коли штучний інтелект замінить QA, я також зроблю невдоволене обличчя і скажу, що мені це не подобається :)

Скорее BA перетянут эту функциональность. Т.к. как сомотоятельные единицы на проектах средней руки они не надо, но поумнее чем QA, да и AC они прекрастно знают, .т.к. еще о/во время груминга утрсали с заказчиком...... но это все мечты :)

Подписаться на комментарии