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

Spring Boot Reactive Ripper Joker 2019

Spring Boot Reactive Ripper Joker 2019

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

Как нам избежать сломанных пальцев и разбитых молотком вещей при попытке внедрить React?

Мы рассмотрим пример системы, в которой есть проблемы и, конечно же, попробуем отрефакторить её в реактивном стиле. Рассмотрим преимущества и недостатки не только подхода, но и API конкретных реализаций. Оценим сложность, которая была до рефакторинга, и ту сложность, которую мы привнесли после. Постараемся разобраться что игрушки, а что нет.

Kirill Tolkachev

October 24, 2019
Tweet

More Decks by Kirill Tolkachev

Other Decks in Technology

Transcript

  1. Улучшения 1. Начало перенести в слайды и дропнуть демку ради

    упростить 2. Упростить, чтобы былее очевидно ЗАЧЕМ ЭТО может понадобиться. Кажется кейсы Мы сначала сделали а потом огребли, плохо сработали 3. В конце не успевали, лучше более подробно последнюю часть вместо первой 4. В этот раз придётся рассказывать про rSocket т.к не стоит рассчитывать что перед нами будет доклад докуки 5. Список докладов на посмотреть в конце( егорова + докуки)
  2. Архитектура проекта «Big Brother» Перехватчик писем, отсылает все письма на

    распознание Правоохранительные органы, принимают решение об аресте Расшифровщик писем, Выясняет чьё письмо о отсылает в Правоохранительные органы
  3. Архитектура с RestTemplate и loop - Заканчиваются connection на tomcat

    → жопа - Про стартер. Как он используется. Какие эндпоинты добавляет - Какие настройки есть, как сервисы находят друг друга - Какие вещи нужно было бы добавить ещё в стартер чтобы он стал действительно полезным и универсальным - Понимаем что дописывать эти вещи сложно и мы хотим WebFlux Картиночка с котом с оторванным хвостом
  4. Архитектура с RestTemplate и loop Ещё N пожалуйста Вот N

    писем Ещё N пожалуйста Вот N писем
  5. restTemplate.postForEntity( "http://localhost:8081/analyse/letter", Letter, Void.class ); Смерть через RestTemplate restTemplate.getForObject( adjustmentProperties.getUrl()

    + "/" + n, id.class restTemplate.postForEntity( "http://localhost:8081/analyse/letter", Letter, Void.class ); restTemplate.postForEntity( "http://localhost:8081/analyse/letter", Letter, Void.class );
  6. Тут не показываем табличку а показываем тома Понятно что тут

    ничего не работает, но потом будут интересные метрики - Разъяснить про табличку. Что в ней что значит и как её читать
  7. Tomcat Push and Pull semantics related to consumer events Pusher

    Buffer #P0 Passive Consumer Buffer #C2 Buffer #T1 Wait
  8. Tomcat Push and Pull semantics related to consumer events Pusher

    Buffer #P0 Passive Consumer Buffer #C2 Buffer #T1 Wait
  9. Tomcat Push and Pull semantics related to consumer events Pusher

    Buffer #P0 Passive Consumer Buffer #C2 Buffer #T1 Reject
  10. ...

  11. Что должен делать producer когда consumer не справляется Продюсер читает

    данные с нужной скоростью Нет проблемы В продюсер текут данные Всё что не успеваем отослать, суем в очередь, когда нет места в очереди, дропаем, то что менее важно
  12. Push and Pull semantics related to consumer events Pusher Buffer

    #P0 Passive Consumer Or batch single Buffer #C2
  13. Push and Pull semantics related to consumer events Pusher Buffer

    #P0 Passive Consumer Or batch single Buffer #C2
  14. Tomcat Push and Pull semantics related to consumer events Pusher

    Buffer #P0 Passive Consumer Buffer #C2 Buffer #T1 Wait
  15. Tomcat Push and Pull semantics related to consumer events Pusher

    Buffer #P0 Passive Consumer Buffer #C2 Buffer #T1 Wait
  16. Tomcat Push and Pull semantics related to consumer events Pusher

    Buffer #P0 Passive Consumer Buffer #C2 Buffer #T1 Reject
  17. Push and Pull semantics related to consumer events Pusher Buffer

    #P0 Passive Consumer Buffer #C2 Black Hole
  18. Push and Pull semantics related to consumer events Pull &

    Push Service Passive Consumer Buffer #C2 Black Hole Buffer #P0
  19. Push and Pull semantics related to consumer events Pull &

    Push Service Passive Consumer Buffer #C2 Black Hole Buffer #P0
  20. Push and Pull semantics related to consumer events Pull &

    Push Service Passive Consumer Buffer #C2 Black Hole Buffer #P0
  21. WebClient is a new RestTemplate Было RestTemplateBuilder → RestTemplate RestTemplate

    — передаём статический текс в body Стало WebClient.Builder → WebClient WebClient — можем передать последовательность Flux в качестве body
  22. exchange WebClient reactor-netty jetty-client Java 11 http client Issue 19658

    subscribe Issue 21014 Flux closed open Controller http connection
  23. void processLetter(Flux<Letter> f) f.doOnNext() .doOnNext() .log() .subscribe() return Mono.empty() /

    nothing / anything LetterController Close connection 400 BAD_REQUEST "Request body is missing
  24. void processLetter(Flux<Letter> f) f.doOnNext() .doOnNext() .log() .subscribe() return Mono.empty() /

    nothing / anything LetterController Close connection 400 BAD_REQUEST "Request body is missing Для начала вычитывания
  25. Flux пайплайн жизненный цикл 1. Assembly Как new Builder().prop().build() Только

    Flux.create().subscribe(subscriber) 2. В subscriber.onSubscribe() передаётся подписка – subscription 3. Через subscription выполняется первый запрос на ивенты или отписка
  26. Mon<Void> processLetter(Flux<Letter> f) return f.doOnNext() .flatMap( letter -> Mono.fromCallable(() ->

    decode(letter)) .subscribeOn(fromExecutor(threadPool)), threadPool.getMaximumPoolSize()) .log() .then() LetterController reactor-netty
  27. А что с нашими DirectBuffer`ами? netty java.lang.OutOfMemoryError: Direct buffer memory

    at j.n.Bits.reserveMemory(Bits.java:175) at j.n.DirectByteBuffer.<init>(DirectByteBuffer.java:118)
  28. А что с нашими DirectBuffer`ами? netty java.lang.OutOfMemoryError: Direct buffer memory

    at j.n.Bits.reserveMemory(Bits.java:175) at j.n.DirectByteBuffer.<init>(DirectByteBuffer.java:118)
  29. Почувствуйте разницу [letter-4] onNext [letter-4] onNext [letter-2] onNext [letter-1] onNext

    [letter-4] onNext [letter-3] onNext [reactor-http-nio-3] onNext [reactor-http-nio-3] onNext [reactor-http-nio-3] onNext [reactor-http-nio-3] onNext [reactor-http-nio-3] onNext [reactor-http-nio-3] onNext vs
  30. TCP BP Без flatMap #0 flux netty netty flux reactor-netty

    reactor-nio-1 Без flatMap Пулы DirectBuffer`ов netty socket
  31. TCP BP Без flatMap #1 flux netty netty flux reactor-netty

    reactor-nio-1 Пулы DirectBuffer`ов netty socket 1. Копирует данные из cистемного сокета в DirectBuffer
  32. TCP BP Без flatMap #2 flux netty netty flux reactor-netty

    reactor-nio-1 Пулы DirectBuffer`ов netty socket 1. Копирует данные из cистемного сокета в DirectBuffer 2. Вызывает наш медленный метод decoder.decode LetterController.java
  33. TCP BP Без flatMap #3 flux netty netty flux reactor-netty

    reactor-nio-1 Пулы DirectBuffer`ов netty socket 1. Копирует данные из cистемного сокета в DirectBuffer 2. Вызывает наш медленный метод decoder.decode LetterController.java 3. Копирует данные из cистемного сокета в DirectBuffer
  34. TCP BP Без flatMap #3 flux netty netty flux reactor-netty

    reactor-nio-1 Пулы DirectBuffer`ов netty socket 1. Копирует данные из cистемного сокета в DirectBuffer 2. Вызывает наш медленный метод decoder.decode LetterController.java 3. Копирует данные из cистемного сокета в DirectBuffer 4. ... и так повторяется
  35. TCP BP После добавления flatMap flux netty netty flux reactor-netty

    reactor-nio-1 letter-N Пулы DirectBuffer`ов netty socket 1. Копирует данные из cистемного сокета в [1ms] DirectBuffer
  36. TCP BP После добавления flatMap flux netty netty flux reactor-netty

    reactor-nio-1 letter-N Пулы DirectBuffer`ов netty socket 1. Вызывает наш медленный метод [1000ms] decoder.decode LetterController.java
  37. TCP BP После добавления flatMap flux netty netty flux reactor-netty

    reactor-nio-1 letter-N Пулы DirectBuffer`ов netty socket 1. Копирует данные из cистемного сокета в [1ms] DirectBuffer [1000ms]
  38. TCP BP После добавления flatMap flux netty netty flux reactor-netty

    reactor-nio-1 letter-N Пулы DirectBuffer`ов netty socket [1000ms] letter-N Копирует данные из cистемного сокета в DirectBuffer [1ms] Вызывает наш медленный метод decoder.decode LetterController.jav a [1000ms] работает независимо
  39. TCP BP После добавления flatMap flux netty netty flux reactor-netty

    reactor-nio-1 letter-N Пулы DirectBuffer`ов netty socket Копирует данные из cистемного сокета в DirectBuffer [1ms] [1000ms] Вызывает наш медленный метод decoder.decode LetterController.jav a [1000ms] работает независимо
  40. А что с нашими DirectBuffer`ами? netty java.lang.OutOfMemoryError: Direct buffer memory

    at j.n.Bits.reserveMemory(Bits.java:175) at j.n.DirectByteBuffer.<init>(DirectByteBuffer.java:118)
  41. А как встроен? $ ./gradlew :pechkin-service:dI --dependency io.rsocket:rsocket-core io.rsocket:rsocket-core:1.0.0-RC5 +---

    org.springframework.boot:spring-boot-dependencies:2.2.0.RELEASE (*) \--- org.springframework.boot:spring-boot-starter-rsocket:2.2.0.RELEASE (*)
  42. Сияющие технологии 1. В каких то задачах Webflux будет хорош

    a. Нет потребности в контроле Backpressure но внутри есть реактивная логика b. Быстрая интеграция с существующими API Reactor 2. В каких то задачах RSocket будет плох 3. Но своё решение всегда как минимум заставляет задуматься
  43. Hand Made Starter Webflux RSocket Максимальное использование ресурсов + +

    + Максимально быстро +- + + Backpressure - - +- Всё из коробки - +- + Просто использовать - - -
  44. Выводы 1. Не всё то Reactive что с интегрировано с

    Project Reactor a. Поддержка Backpressure на основе TCP BP имеет сайд эффекты b. Control flow между сервисами для реактивного пайплайна так же важен 2. Webflux не подходит для балансировки скорости между сервисами 3. С RSocket честный backpressure, перспективно 4.
  45. Настоящие выводы Не стоит внедрять технологии на основе авторитета: 1.

    спикера 2. компании 3. Тренда Webflux хорош когда нужно сэкономить коннекшены и отправить пачку данных RSocket хорош во всех наших кейсах Свой велосипед всегда понятнее
  46. Выводы – кривая обучения reactive effort/time Holy moly I am

    god! Wow It’s works This doesnt work Why can’t i get it to work Learn about reactive mastery
  47. Ссылки Код с демо 1. https://github.com/lavcraft/spring-react-or-not-react-jpoint2019 Spring Webflux Streaming 1.

    Json streaming 2. Jackson Smile Spring WebClient 1. WebClient Java 11 HttpClient Support 2. Webflux and RSocket backpressure Rsocket 1. Rsocket.io 2. Протокол RSocket – будущее. Доклад Олега Докуки