Page 1
Однажды одна выдуманная команда разработчиков собралась вместе и решила попробовать микросервисы.
Эта выдуманная история расскажет о трудностях, которые встретились у смелых разработчиков на пути и об отваге, с которой эти трудности преодолевались.
Все совпадения случайны, мнение автора может не совпадать с мнением других выдуманных участников истории.
Автор не несет ответственности за возможный сдвиг парадигмы у слушателей и вообще считает его очень полезным для развития.
Page 2
Сячин Максим
Место работы: Luxoft SPB Заказчик: Почта России
Опыт разработки: 11 лет Java, C++, Kotlin, Scala
twitter: @finnetrolle github: finnetrolle
[email protected]
Page 3
МикросервисыПервая кровь
Page 5
План нашей встречи• Проблемы на старте разработки
• Проблемы во время разработки
• Проблемы при тестировании
• А что взамен?
Page 6
Микросервисы могут быть настолько же эффективны, насколько они обязательно
окажутся сложны.
Page 7
Начало проектакогда одно решение определяет дальнейшую историю
Page 8
Монолит Микросервисы
Simplicity Partial deployment
Consistency Availability
Inter-module refactoring Preserve modularity
Multiple platforms
Page 9
Monolith vs MicroservicesС чего лучше начинать?
Page 10
Monolith vs MicroservicesС чего лучше начинать?
Page 11
Monolith vs MicroservicesС чего лучше начинать?
Page 12
Monolith vs MicroservicesС чего лучше начинать?
Page 13
Monolith Firstнеоднозначное решение
Page 15
• Нет влияния на функциональные требования, в следствие чего не выделяются ресурсы на рефакторинг
• Монолит провоцирует высокую связанность, отделять микросервисы тем сложнее, чем старше монолит
Page 16
Деление на микросервисынесколько сложнее, чем разрезание пиццы
Page 17
N-layer архитектура
Presentation Layer
Business Layer
Data Access Layer
Web application
Business logic microservice
Data microservice
Page 18
Однородные команды разработки
UI разработчики
Backend разработчики
DBA
Page 19
– M. Conway
« Организация которая разрабатывает систему ... вынуждена делать систему по
структуре повторяющую структуру коммуникаций внутри организации»
Page 20
Гетерогенные команды разработки
Управление финансами
Склад
CRM
Page 21
Don't repeat yourselfили как избавиться от преимуществ микросервисов
Page 22
Библиотека common
Ваше первое и основное
приложение
Модуль A
Модуль B
Модуль C
Utils
Utils
Utils
Common
Page 23
Библиотека common
Приложение А
common
Приложение B Приложение C
A + B B + C
A + C A+B+C
Приложение А новая версия
Приложение B новая версия
Приложение C новая версия
common
Page 24
Библиотека common, DTO и клиенты
App 5 DTOApp 4DTO
App 2 DTO App 3 DTOApp 1DTO
Один большой и очень умный
common
клиент для App 1клиент для App 2клиент для App 3клиент для App 4клиент для App 5
DTO
клиент для App 5
Общая библиотека common стала
умнееApp 5
App 3App 2App 1
App 4
Page 25
Библиотека с общим APIКлиентские приложения
Умный балансировщик
Оплата через Капут-банк
Оплата через Банк "Гибкость"
Капут-банк Банк "Гибкость"
REST
REST REST
Оплата common
Page 26
Библиотека с общим API
DTO оплаты
Общий API
Умный Балансировщик
Оплата через Капут-банк
Оплата через Банк "Гибкость"
Стандартный протокол оплаты Особенность оплаты
через "Гибкость"
DTO оплаты
Общий API
Умный Балансировщик
Оплата через Банк "Гибкость"
Оплата через Капут-банк
Page 27
Собственный фасад для REST клиента
Jersey client
Собственный REST клиент
client.post(PATH) .withParam("id", id) .withBody(body) .forEntityOf(Resp.class) .orElseThrow(RestError::new)
Клиент к приложению А
Приложение B Приложение C Приложение D
Собственный REST клиент
DTO для приложения А
Собственный REST клиент
client.post(PATH) .withParam("id", id) .withBody(body) .forResponse(Resp.class) .orElseThrow(RestError::new)
Клиент к приложению А
Приложение B Приложение C Приложение D
Page 28
Собственный фасад для REST клиента
Jersey client
Собственный REST клиент
Клиент к приложению А
Приложение B Приложение C Приложение D
Собственный REST клиент
DTO для приложения А
client.post(PATH) .withParam("id", id) .withBody(body) .forResponse(Resp.class) .orElseThrow(RestError::new)
Собственный REST клиент
Клиент к приложению А
Приложение B
Client v. 1.0.1 Client v. 1.0.0 Client v. 1.0.0
Page 29
Собственный фасад для REST клиента
Приложение А
Приложение B
Приложение C
Приложение D
Приложение E
Client A v 1.0.1
Client A v 1.0.23
Client A v 1.2.10
Page 30
Советы по DRY
• Старайтесь обойтись в библиотеках без доменных объектов
• Сильное сцепление и низкая связанность уменьшат потребность в разделяемых библиотеках
• Используйте стабильные библиотеки
Page 31
ИнтеграцияКошмар поддержки чужих изменений
Page 32
DTO Hell
Приложение "Каталог двигателей"
engines-dto
Приложение "Страховка"
Приложение "Ремонт авто"
Приложение "Автоподбор для
клиента"
Приложение "Оценка авто"
Приложение "Конструктор"
Page 33
DTO Hell
Приложение "Каталог двигателей"
engines-dto
Приложение "Страховка"
Приложение "Ремонт авто"
С++ QTПриложение
"Автоподбор для клиента"
Приложение "Оценка авто"
Приложение "Конструктор"
Page 34
Композитный response{ "id":18, "model":"Rav4", "engines":[ {"name":"4m40", "power":200, "id":101}, {"name":"100kz", "power":250, "id":287} ], "exteriors":[ {"color":"BLACK", "type":"BASIC", "id":334}, {"color":"WHITE", "type":"BASIC", "id":422}, {"color":"WHITE", "type":"DULL", "id":451} ], "transmissions":[ {"type":"AUTO", "gears":5, "id":334}, {"type":"AUTO", "gears":6, "id":335}, {"type":"MANUAL","gears":5, "id":354} ] }
Page 35
Композитный response{ "id":18, "model":"Rav4", "engines":[ {"name":"4m40", "power":200, "id":101}, {"name":"100kz", "power":250, "id":287} ], "exteriors":[ {"color":"BLACK", "type":"BASIC", "id":334}, {"color":"WHITE", "type":"BASIC", "id":422}, {"color":"WHITE", "type":"DULL", "id":451} ], "transmissions":[ {"type":"AUTO", "gears":5, "id":334}, {"type":"AUTO", "gears":6, "id":335}, {"type":"MANUAL","gears":5, "id":354} ] }
Какие автоматические коробоки передач поставляются с Toyota Rav4?
http://someurl.com/api/vehicle/18
Page 36
Композитный response
[ {"type":"AUTO", "gears":5, "id":334}, {"type":"AUTO", "gears":6, "id":335} ]
Какие автоматические коробоки передач поставляются с Toyota Rav4?
http://someurl.com/api/vehicle/18/transmissions?type=AUTO
Page 37
Советы по интеграции
• Паттерн Expand and Contract
• Семантика версий [major.minor.patch]
• Protobuf, Thrift
Page 38
– Джон Постел
«Будь либерален к тому, что принимаешь, и требователен к тому, что отсылаешь».
Page 39
Сложности тестированиячто работает само по себе не обязательно заработает
в связке с соседями
Page 40
Воссоздание окружения для тестирования
Приложение, которое надо протестировать
Какой-нибудь HTTP клиент
(PAW, SoapUI)Локальная СУБД
Это приложение поставляет нам
данныеКстати, ему тоже
нужна СУБД
И еще одно приложение, тоже со своей СУБД
А это приложение стороннего
разработчика и висит в интернете
Page 41
Проблема асинхронных сервисов
Приложение, которое надо протестировать
Какой-нибудь HTTP клиент
(PAW, SoapUI)
Стороннее приложение, висящее
в интернете и работающее в
асинхронном режиме
Page 42
Как воссоздаем?
• Dummy внутри микросервиса (активируется настройкой)
• Запуск сервисов с данными
• Отладочные прокси (Fiddler)
• Dummy микросервисы
Page 44
Разбираемся с логами
• Elasticsearch + Logstash + Kibana
• Elasticsearch + FluentD + Kibana
• Сторонние сервисы (Loggly, Papertrail)
• Logging to stdout + docker logs
Page 45
История успехаПозитивные моменты разработки
Page 46
Проверка и внедрение новых технологий
Page 47
High maintainability• Быстро входишь в контекст небольшого сервиса даже после длительного перерыва
• Меньше путаного кода
• Изменения в одном сервисе редко задевают другие
• Задачи, затрагивающие несколько сервисов, легко делятся на подзадачи
Page 48
Высокая надежность
• Stateless сервисы легко масштабируются горизонтально
• Healthcheck + мониторинг + быстрый запуск позволяют не бояться падения приложения
Page 49
• Пока идет знакомство с микросервисами, разработка сложна, а последствия неверных решений раздражают
• По мере взросления технологии, все больше внимания уделяется задаче, а не бойлерплейту
• Однажды наступает момент, когда в ответ на список новых требований вы просто запускаете новый микросервис
Page 50
Спасибо за внимание!Настало время вопросов