DEV Labs 2016. Микросервисы - первая кровь

Preview:

Citation preview

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

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

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

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

Сячин Максим

Место работы: Luxoft SPB Заказчик: Почта России

Опыт разработки: 11 лет Java, C++, Kotlin, Scala

twitter: @finnetrolle github: finnetrolle

maxsyachin@gmail.com

МикросервисыПервая кровь

70100

19900

План нашей встречи• Проблемы на старте разработки

• Проблемы во время разработки

• Проблемы при тестировании

• А что взамен?

Микросервисы могут быть настолько же эффективны, насколько они обязательно

окажутся сложны.

Начало проектакогда одно решение определяет дальнейшую историю

Монолит Микросервисы

Simplicity Partial deployment

Consistency Availability

Inter-module refactoring Preserve modularity

Multiple platforms

Monolith vs MicroservicesС чего лучше начинать?

Monolith vs MicroservicesС чего лучше начинать?

Monolith vs MicroservicesС чего лучше начинать?

Monolith vs MicroservicesС чего лучше начинать?

Monolith Firstнеоднозначное решение

• Нет влияния на функциональные требования, в следствие чего не выделяются ресурсы на рефакторинг

• Монолит провоцирует высокую связанность, отделять микросервисы тем сложнее, чем старше монолит

Деление на микросервисынесколько сложнее, чем разрезание пиццы

N-layer архитектура

Presentation Layer

Business Layer

Data Access Layer

Web application

Business logic microservice

Data microservice

Однородные команды разработки

UI разработчики

Backend разработчики

DBA

– M. Conway

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

структуре повторяющую структуру коммуникаций внутри организации»

Гетерогенные команды разработки

Управление финансами

Склад

CRM

Don't repeat yourselfили как избавиться от преимуществ микросервисов

Библиотека common

Ваше первое и основное

приложение

Модуль A

Модуль B

Модуль C

Utils

Utils

Utils

Common

Библиотека common

Приложение А

common

Приложение B Приложение C

A + B B + C

A + C A+B+C

Приложение А новая версия

Приложение B новая версия

Приложение C новая версия

common

Библиотека 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

Библиотека с общим APIКлиентские приложения

Умный балансировщик

Оплата через Капут-банк

Оплата через Банк "Гибкость"

Капут-банк Банк "Гибкость"

REST

REST REST

Оплата common

Библиотека с общим API

DTO оплаты

Общий API

Умный Балансировщик

Оплата через Капут-банк

Оплата через Банк "Гибкость"

Стандартный протокол оплаты Особенность оплаты

через "Гибкость"

DTO оплаты

Общий API

Умный Балансировщик

Оплата через Банк "Гибкость"

Оплата через Капут-банк

Собственный фасад для 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

Собственный фасад для 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

Собственный фасад для REST клиента

Приложение А

Приложение B

Приложение C

Приложение D

Приложение E

Client A v 1.0.1

Client A v 1.0.23

Client A v 1.2.10

Советы по DRY

• Старайтесь обойтись в библиотеках без доменных объектов

• Сильное сцепление и низкая связанность уменьшат потребность в разделяемых библиотеках

• Используйте стабильные библиотеки

ИнтеграцияКошмар поддержки чужих изменений

DTO Hell

Приложение "Каталог двигателей"

engines-dto

Приложение "Страховка"

Приложение "Ремонт авто"

Приложение "Автоподбор для

клиента"

Приложение "Оценка авто"

Приложение "Конструктор"

DTO Hell

Приложение "Каталог двигателей"

engines-dto

Приложение "Страховка"

Приложение "Ремонт авто"

С++ QTПриложение

"Автоподбор для клиента"

Приложение "Оценка авто"

Приложение "Конструктор"

Композитный 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} ] }

Композитный 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

Композитный response

[ {"type":"AUTO", "gears":5, "id":334}, {"type":"AUTO", "gears":6, "id":335} ]

Какие автоматические коробоки передач поставляются с Toyota Rav4?

http://someurl.com/api/vehicle/18/transmissions?type=AUTO

Советы по интеграции

• Паттерн Expand and Contract

• Семантика версий [major.minor.patch]

• Protobuf, Thrift

– Джон Постел

«Будь либерален к тому, что принимаешь, и требователен к тому, что отсылаешь».

Сложности тестированиячто работает само по себе не обязательно заработает

в связке с соседями

Воссоздание окружения для тестирования

Приложение, которое надо протестировать

Какой-нибудь HTTP клиент

(PAW, SoapUI)Локальная СУБД

Это приложение поставляет нам

данныеКстати, ему тоже

нужна СУБД

И еще одно приложение, тоже со своей СУБД

А это приложение стороннего

разработчика и висит в интернете

Проблема асинхронных сервисов

Приложение, которое надо протестировать

Какой-нибудь HTTP клиент

(PAW, SoapUI)

Стороннее приложение, висящее

в интернете и работающее в

асинхронном режиме

Как воссоздаем?

• Dummy внутри микросервиса (активируется настройкой)

• Запуск сервисов с данными

• Отладочные прокси (Fiddler)

• Dummy микросервисы

Собираем логи

Разбираемся с логами

• Elasticsearch + Logstash + Kibana

• Elasticsearch + FluentD + Kibana

• Сторонние сервисы (Loggly, Papertrail)

• Logging to stdout + docker logs

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

Проверка и внедрение новых технологий

High maintainability• Быстро входишь в контекст небольшого сервиса даже после длительного перерыва

• Меньше путаного кода

• Изменения в одном сервисе редко задевают другие

• Задачи, затрагивающие несколько сервисов, легко делятся на подзадачи

Высокая надежность

• Stateless сервисы легко масштабируются горизонтально

• Healthcheck + мониторинг + быстрый запуск позволяют не бояться падения приложения

• Пока идет знакомство с микросервисами, разработка сложна, а последствия неверных решений раздражают

• По мере взросления технологии, все больше внимания уделяется задаче, а не бойлерплейту

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

Спасибо за внимание!Настало время вопросов

Recommended