Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Как перейти на микросервисы и не разломать production

Как перейти на микросервисы и не разломать production

Опыт перевода приложения с монолитной архитектуры на микросервисы:
Причина перехода на МС архитектуру
Процесс перехода: какие технологии и почему
Плюсы и минусы перехода
Кластеризация приложения и как это повлияло на работу с данными
Подводные камни

Dmitrii Rygalov

October 11, 2018
Tweet

More Decks by Dmitrii Rygalov

Other Decks in Technology

Transcript

  1. Copyright © Eastbanc Technologies 2018. All rights reserved. 2018 Как

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

    на микросервисы 1. Приложение и основные его тех. задачи 2. Причина перехода на МС архитектуру 3. Процесс перехода: какие технологии и почему 4. Плюсы и минусы перехода 5. Кластеризация приложения и как это повлияло на работу с данными 6. Подводные камни, которые мы собрали 7. Docker 3
  3. Кто хочет понять, нужно ли его проекту переходить с монолита

    на микросервисы? Кто ты и зачем здесь? J 4 Кто уже начал переводить? У кого текущий проект изначально на микросервисах? А кто пришёл похоливарить на эту тему?
  4. 1. MySQl 2. Tomcat (с единственным war) • Maven •

    Spring (core mvc security) • SAML • Hibernate • Static (UI - SPA) 3. Nginx 4. ELK (elastic, logstash, kibana) MySQL Tomcat (Spring) Proxy (Nginx) ELK Архитектура v0 8
  5. Развитие архитектуры и её недостатки • Разработка на основе сценариев

    (use case) • Большая часть сценариев укладывалась в work-flow, но не все Следствия • Сложная разработка • Не можем проводить «Глубокое проектирование» MySQL Tomcat (Spring) Proxy (Nginx) ELK 9
  6. CI/CD на старте Разработка по git-flow Поставка артефактов через Jenkins

    1. DEV по комиту 2. QA раз в сутки или по требованию 3. PROD по требованию 14
  7. Провокаторы и технический долг 1. Изменяющиеся use cases 2. Простой

    при выкатывании новых версий 3. Tomcat Session Management 4. Redeploy memory leak 16
  8. Начнём с: 1. Изменяющиеся use cases 2. Простой при выкатывании

    новых версий 3. Tomcat Session Management 4. Redeploy memory leak 17
  9. 1. Взаимодействие по http 2. Spring Boot для создания сервисов

    Tomcat Wars seat-pricing root-app Первый микросервис: взаимодействия модуль 1 19
  10. Основной подход к выделению микросервисов: 1. Типы бизнес-услуг (или бизнес-функций)

    2. Интеграция со сторонними сервисами Принцип распила Tomcat Wars currency rates print-forms … seat bag ticket модулей 13 21
  11. Итог №1 1. Изменяющиеся use cases 2. Простой при выкатывании

    новых версий 3. Tomcat Session Management 4. Redeploy memory leak модулей 13 22
  12. Проблемы росли как снежный ком 5. Типизация и версионирование Dto

    1. Изменяющиеся use cases 2. Простой при выкатывании новых версий 3. Tomcat Session Management 4. Redeploy memory leak модулей 14 23
  13. Проблемы типизации Dto Даже небольшие изменения ведут не только к

    удобству, но и к новым проблемам модулей 15 seat bag ticketing currency rates print-forms … meal geography Tomcat Wars 24
  14. Как решить? 25 interface Client { Res get(Req req); }

    @RestController(“/p1”) class Controller iml Client { @PostMapping(“/p2”) Res get(Req req) {return new Res();}} class ClientImpl iml Client { Res get(Req req) {return restTemplate.post(“host/p1/p2”, req)}}
  15. Наши требования: Есть ли альтернативы? 26 1. Минимум изменений 2.

    Желательно использовать подход с интерфейсами 3. Ещё лучше – «Не писать код»
  16. RestTemplate vs Apache CXF vs OpenFeign 1. RestTemplate синхронный http

    client, работающий поверх JDK HttpURLConnection, Apache HttpComponents, и т.д. 2. Apache CXF имплементация JAX-RS-2.0 3. OpenFeign http client library, вдохновлённый Retrofit, JAX-RS-2.0 27
  17. RestTemplate + + - - Опыт использования / он уже

    есть в проекте Большой пласт уже написанного кода Может измениться путь до метода и нужно отслеживать и менять в двух местах Нужно писать код (заворачивать все места использования в сервисы) 28
  18. @Path("/p1") interface Client { @GET @Path(“/p2”) Res get(); } class

    Controller iml Client { Res get() {return new Res();}} Client c = JAXRSClientFactory.create(”http://server", Client.class); Apache CXF 29
  19. Apache CXF + + + - Опыт использования / простота

    Имплементирует JAX-RS (звучит круто, всё-таки стандарт) April 16, 2018 - 10 years of CXF - Happy Birthday! всё ещё активный проект Нужно изменить контроллеры (и подключить Jersey) 30
  20. interface Client { @PostMapping(“/p2”) Res get(Req req); } @RestController(“/p1”) class

    Controller iml Client { Res get(Req req) {return new Res();}} @FeignClient(“host/p1”) interface ClientImpl iml Client { } Spring Cloud Feign 32
  21. Простота Имплементирует JAX-RS (уже не интересно) Spring Cloud Feign –

    поддержка аннотаций Spring Первоначальная конфигурация пришлось отключить Ribbon & Hystrix Spring Cloud Feign + + - + 33
  22. Итог №2 1. Изменяющиеся use cases 2. Простой при выкатывании

    новых версий 3. Tomcat Session Management 4. Redeploy memory leak 5. Проблемы типизации и версионирования Dto модулей 17 34
  23. ~ 18 модулей * N серверов Архитектура v1 модулей 18

    Датацентр #1 HAProxy Tomcat MySQL Filebeat Датацентр #N HAProxy Tomcat MySQL Filebeat VPN Сервер ELK Kibana Elasticsearch Logstash VPN 36
  24. Архитектура v1: шардинг модулей 19 ~ 19 модулей * N

    серверов Датацентр #1 HAProxy Tomcat MySQL Filebeat Датацентр #N HAProxy Tomcat MySQL Filebeat VPN Сервер ELK Kibana Elasticsearch Logstash VPN 37
  25. Архитектура v1 1. High availability 2. CI/CD 3. Disaster recovery

    4. Fault tolerance модулей 20 Датацентр #1 HAProxy Tomcat MySQL Filebeat Датацентр #N HAProxy Tomcat MySQL Filebeat VPN Сервер ELK Kibana Elasticsearch Logstash VPN 38
  26. В 4 часа ночи после релиза… модулей 20 39 0x000000004a486800

    JavaThread "pool-2-thread-6" [_thread_blocked, id=47808, stack(0x0000000051300000,0x0000000051400000)] 0x000000004a486000 JavaThread "pool-2-thread-5" [_thread_blocked, id=32884, stack(0x0000000000ce0000,0x0000000000de0000)] 0x000000004a484800 JavaThread "pool-2-thread-4" [_thread_blocked, id=45632, stack(0x0000000052ee0000,0x0000000052fe0000)] 0x000000004a483800 JavaThread "pool-2-thread-3" [_thread_blocked, id=48724, stack(0x0000000052de0000,0x0000000052ee0000)] 0x000000004a483000 JavaThread "pool-2-thread-2" [_thread_blocked, id=37828, stack(0x0000000052ce0000,0x0000000052de0000)] 0x000000004a482000 JavaThread "pool-2-thread-1" [_thread_blocked, id=47084, stack(0x00000000517f0000,0x00000000518f0000)] 0x000000004a480000 JavaThread "http-apr-8080-exec-10" daemon [_thread_blocked, id=42448, stack(0x0000000052be0000,0x0000000052ce0000)] 0x000000004a47f000 JavaThread "http-apr-8080-exec-9" daemon [_thread_blocked, id=38780, stack(0x00000000516f0000,0x00000000517f0000)] 0x000000004a47e800 JavaThread "http-apr-8080-exec-8" daemon [_thread_blocked, id=41084, stack(0x00000000519e0000,0x0000000051ae0000)] 0x000000004af76000 JavaThread "http-apr-8080-exec-7" daemon [_thread_blocked, id=44868, stack(0x0000000051b10000,0x0000000051c10000)] 0x000000004a47d800 JavaThread "http-apr-8080-exec-6" daemon [_thread_blocked, id=41464, stack(0x0000000050ed0000,0x0000000050fd0000)] 0x000000004a47d000 JavaThread "http-apr-8080-exec-5" daemon [_thread_blocked, id=43256, stack(0x0000000050dd0000,0x0000000050ed0000)] 0x000000004a47c000 JavaThread "http-apr-8080-exec-4" daemon [_thread_blocked, id=33200, stack(0x000000004dce0000,0x000000004dde0000)] 0x000000004ac5c800 JavaThread "http-apr-8080-exec-3" daemon [_thread_blocked, id=31392, stack(0x000000004c5a0000,0x000000004c6a0000)] 0x000000004ac5c000 JavaThread "http-apr-8080-exec-2" daemon [_thread_blocked, id=44984, stack(0x0000000049b20000,0x0000000049c20000)] 0x000000004ac5b000 JavaThread "http-apr-8080-exec-1" daemon [_thread_blocked, id=43804, stack(0x0000000000880000,0x0000000000980000)] 0x000000004ac5a800 JavaThread "ajp-apr-8009-AsyncTimeout" daemon [_thread_blocked, id=35060, stack(0x0000000050cd0000,0x0000000050dd0000)] 0x000000004ac59800 JavaThread "ajp-apr-8009-Acceptor-0" daemon [_thread_in_native, id=54980, stack(0x0000000050bd0000,0x0000000050cd0000)] 0x000000004ac59000 JavaThread "ajp-apr-8009-CometPoller-7" daemon [_thread_blocked, id=54772, stack(0x0000000050ad0000,0x0000000050bd0000)] 0x000000004ac58000 JavaThread "ajp-apr-8009-CometPoller-6" daemon [_thread_blocked, id=33316, stack(0x00000000509d0000,0x0000000050ad0000)] 0x000000004ac57800 JavaThread "ajp-apr-8009-CometPoller-5" daemon [_thread_blocked, id=33916, stack(0x00000000508d0000,0x00000000509d0000)] 0x000000004ac56800 JavaThread "ajp-apr-8009-CometPoller-4" daemon [_thread_blocked, id=33288, stack(0x00000000507d0000,0x00000000508d0000)] 0x000000004ac56000 JavaThread "ajp-apr-8009-CometPoller-3" daemon [_thread_blocked, id=35012, stack(0x00000000506d0000,0x00000000507d0000)] 0x000000004ac55000 JavaThread "ajp-apr-8009-CometPoller-2" daemon [_thread_blocked, id=34340, stack(0x00000000505d0000,0x00000000506d0000)] 0x000000004ac54800 JavaThread "ajp-apr-8009-CometPoller-1" daemon [_thread_blocked, id=54696, stack(0x00000000504d0000,0x00000000505d0000)]
  27. JDK-8039562 Tomcat 7a crashes when using 8 модулей 20 40

    https://bugs.openjdk.java.net/browse/JDK-8039562
  28. 2. Простой при выкатывании новых версий Новая архитектура и её

    старые недостатки 1. Изменяющиеся use cases 3. Tomcat Session Management 4. Redeploy memory leak 5. Проблемы типизации и версионирования Dto 41 21 модуль
  29. 2. Простой при выкатывании новых версий Новая архитектура и её

    старые недостатки 1. Изменяющиеся use cases 3. Tomcat Session Management 4. Redeploy memory leak 5. Проблемы типизации и версионирования Dto 42 21 модуль
  30. Новая архитектура и её старые недостатки 2. Простой при выкатывании

    новых версий 4. Redeploy memory leak 5. Проблемы типизации и версионирования Dto 6. Сonsistency 3. Tomcat Session Management 43 22 модуля
  31. Новая архитектура и её старые недостатки 2. Простой при выкатывании

    новых версий 3. Tomcat Session Management 4. Redeploy memory leak 5. Проблемы типизации и версионирования Dto 6. Сonsistency 44 23 модуля
  32. Новая архитектура и её старые недостатки 2. Простой при выкатывании

    новых версий 3. Tomcat Session Management 4. Redeploy memory leak 5. Проблемы типизации и версионирования Dto 6. Сonsistency 47 модулей 26
  33. Нет consistency данных при редеплое одного из серверов Решение: Шардинг

    – > Репликация Варианты: Hazelcast vs RabbitMQ (other mq) Архитектура V2 + немного Event-driven architecture 48 модулей 26
  34. 49 Reliable Topic 42 43 44 45 . . .

    . N consumer 1 consumer 2 new consumer модулей 27
  35. Архитектура v2 Statistics 1 Statistics N Hazelcast 1 Hazelcast N

    CRUD Create Update Delete Read MySQL 1 MySQL N 50 модулей 28
  36. Hazelcast Event Management Шардинг -> Репликация Датацентр #1 HAProxy JARs

    MySQL Датацентр #N HAProxy JARs MySQL Hazelcast Архитектура v2 51 модулей 28
  37. 52 SEREALISATION ERROR com.hazelcast.nio.serialization.HazelcastSerializationException: There is no suitable de-serializer for

    type 10 at com.hazelcast.nio.serialization.SerializationServiceImpl.toObject(SerializationServiceImpl.java:257) at com.hazelcast.cache.impl.CacheRecordStore.dataToValue(CacheRecordStore.java:112) at com.hazelcast.cache.impl.CacheRecordStore.recordToValue(CacheRecordStore.java:124) at com.hazelcast.cache.impl.AbstractCacheRecordStore.get(AbstractCacheRecordStore.java:766) at com.hazelcast.cache.impl.operation.CacheGetOperation.run(CacheGetOperation.java:50) at com.hazelcast.spi.impl.BasicOperationService$OperationHandler.process(BasicOperationService.java:613) at com.hazelcast.spi.impl.BasicOperationService.runOperationOnCallingThread(BasicOperationService.java:255) at com.hazelcast.spi.impl.BasicInvocation.doInvokeLocal(BasicInvocation.java:276) at com.hazelcast.spi.impl.BasicInvocation.doInvoke(BasicInvocation.java:258) at com.hazelcast.spi.impl.BasicInvocation.invoke(BasicInvocation.java:225) at com.hazelcast.spi.impl.BasicInvocationBuilder.invoke(BasicInvocationBuilder.java:45) at com.hazelcast.client.impl.client.PartitionClientRequest.process(PartitionClientRequest.java:60) at com.hazelcast.client.impl.ClientEngineImpl$ClientPacketProcessor.processRequest(ClientEngineImpl.java:430) at com.hazelcast.client.impl.ClientEngineImpl$ClientPacketProcessor.run(ClientEngineImpl.java:349) at com.hazelcast.spi.impl.ClassicOperationScheduler$OperationThread.process(ClassicOperationScheduler.java:516) at com.hazelcast.spi.impl.ClassicOperationScheduler$OperationThread.doRun(ClassicOperationScheduler.java:494) at com.hazelcast.spi.impl.ClassicOperationScheduler$OperationThread.run( модулей 28
  38. Новая архитектура и её старые недостатки 2. Простой при выкатывании

    новых версий 3. Tomcat Session Management 4. Redeploy memory leak 5. Проблемы типизации и версионирования Dto 6. Сonsistency 54 модулей 29
  39. Как нам жить с тем, что мы делаем? 1. Service

    Discovery 2. Мониторинг 3. Mini monolith 4. Дублирование кода 5. Stateful 55
  40. <properties> около 100 строк с префиксом service.discovery <service.discovery.name.baggage-pricing> localhost </service.discovery.name.baggage-pricing>

    <service.discovery.port.baggage-pricing> 1007 </service.discovery.port.baggage-pricing> <service.discovery.baggage-pricing> http://${service.discovery.name.baggage-pricing}:${service.discovery.port.baggage-pricing} </service.discovery.baggage-pricing> </properties> Service Discovery -> root.pom 56
  41. Service Discovery -> Consul vs Eureka Consul • Не только

    SD, но и может быть config-server’ом Eureka • Часть Neflix стека Spring Simple UI 57
  42. Service Discovery -> Consul vs Eureka Consul • Не только

    SD, но и может быть config-server’ом Eureka • Часть neflix стека • Работа в кластере, работа уровня «дата-центр» • Деплой как jar Spring Simple UI 58
  43. Как нам жить с тем, что мы делаем? 1. Service

    Discovery 2. Мониторинг 3. Mini monolith 4. Дублирование кода 5. Stateful 59 модулей 30
  44. Mini monolith jars bag seat pricing ешслуе seat print-forms bag

    seat pricing Mini monolith api /auth / services / proxy / static systemd 60 модулей 30
  45. Mini monolith api /auth / services / proxy / static

    Proxy -> Zuul core api /auth Static –> NGINX 45c508269f1bb7eeead304bd389a558609d7a39a Add core-ms * 2017-05-22 16:10 Mini monolith 61 33 модуля
  46. Hazelcast — Session Management Hazelcast — Map<SessionUuid, State> Mini monolith

    Proxy -> Zuul core api /auth Static –> NGINX 62 34 модуля
  47. модулей 35 state = hz.get(sessionUuid); return (IState) Proxy.newProxyInstance(сlassLoader, (proxy, method,

    args) -> { Object invoke = method.invoke(state, args); if (method.nameStartsWith("update || set || add")) { hz.put(sessionUuid, state); } return invoke; }); Взлёты и падения производительности 63
  48. Как нам жить с тем, что мы делаем? 1. Service

    Discovery 2. Мониторинг 3. Mini monolith 4. Дублирование кода 5. Stateful 64 модулей 36
  49. 1. Service Discovery 2. Мониторинг 3. Mini monolith 4. Дублирование

    кода 5. Stateful Как нам жить с тем, что мы делаем? Spring Boot Actuator Spring Cloud Sleuth Spring Boot Admin 65 модулей 37
  50. Как нам жить с тем, что мы делаем? 1. Service

    Discovery 2. Мониторинг 3. Mini monolith 4. Дублирование кода 5. Stateful 66 модулей 38
  51. модулей 39 Итого: архитектура v3 Hazelcast MySQL Zuul Nginx (Static)

    HAProxy RootApi Eureka Bag Seat Print-forms Actuators JARs systemd 67
  52. Develop QA Release-candidate Master feature/ 26414-codeshares bug/43933-pnr Merge Request from

    Develop to QA Merge Request from RC to Master Царство Dev Царство QA Царство Tech Царство пользователей Merge Requests to Develop Merge Request from QA to RC bug/33333-critical-error Back Merge CI/CD Внедрение конвейера развертывания 69
  53. • High availability • CI/CD • Disaster recovery • Fault

    tolerance 41 модуль Победа! Hazelcast MySQL Zuul Nginx (Static) HAProxy RootApi Eureka Bag Seat Print-forms Actuators JARs systemd 70
  54. 1. Canary or Blue-green deployment 2. Domain-driven design 3. Stateless

    4. Single responsibility principle 5. Flexible architecture 6. CQRS and Event Sourcing 42 модуля Что мы имеем в итоге? 71