Доклад. Могут ли Virtual threads заменить Webflux.md
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Struchkov Mark 2024-10-03 09:04:52 +03:00
parent 64ffad807c
commit dd58445116
No known key found for this signature in database
GPG Key ID: A3F0AC3F0FA52F3C
41 changed files with 271 additions and 2 deletions

View File

@ -5,6 +5,7 @@ aliases:
- блокирующий вызов
- блокирующий ввод-вывод
- блокирующего
- блокирующей операции
tags:
- maturity/🌱
date:

View File

@ -7,6 +7,9 @@ aliases:
- нити ос
- нити операционной системы
- нить ос
- потоку
- потоком ОС
- потоку ОС
tags:
- maturity/🌱
date: 2024-01-28

25
dev/java/Java 21 LTS.md Normal file
View File

@ -0,0 +1,25 @@
---
aliases:
- java 21
tags:
- maturity/🌱
date: "[[2023-11-08]]"
zero-link: []
parents:
linked:
---
- [[Java Virtual Threads|Java Virtual Threads]]
***
## Мета информация
**Область**:: [[../../meta/zero/00 Java разработка|00 Java разработка]]
**Родитель**::
**Источник**::
**Автор**::
**Создана**:: [[2023-11-08]]
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
- [[Java Virtual Threads]]
<!-- SerializedQuery END -->

View File

@ -0,0 +1,32 @@
---
aliases:
- виртуальные потоки
- виртуальный поток
- виртуальных потоков
tags:
- maturity/🌱
date: 2024-10-03
zero-link:
parents:
linked:
---
Виртуальный поток не привязан к конкретному [[../fundamental/Поток процесса ОС|потоку ОС]]. При вызове [[../architecture/Блокирующий вызов|блокирующей операции]] Java останавливает этот поток, до момента пока его можно будет вызвать. То есть мы освобождаем настоящий поток ОС, чтобы он не простаивал.
![[../../../../garden/ru/meta/files/images/Pasted image 20241003081726.png]]
В виртуальных потоках не рекомендуется использовать ThreadLocal.
Виртуальный поток не поможет вам, если ваши операции требуют активной работы CPU.
***
## Мета информация
**Область**:: [[../../../../garden/ru/meta/zero/00 Java разработка|00 Java разработка]]
**Родитель**:: [[../../../../garden/ru/dev/java/Java 21 LTS|Java 21 LTS]]
**Источник**::
**Создана**:: [[2024-10-03]]
**Автор**::
### Дополнительные материалы
- [Примеры · GitHub](https://github.com/petrelevich/jvm-digging/tree/master/virtual-thread)
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

@ -0,0 +1 @@
de6bbeb59e7f968b70fba8fc6cd72488

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

View File

@ -0,0 +1 @@
79ae40ee77e2be2b1b3487299c015919

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

View File

@ -0,0 +1 @@
f3af942d08fb6dc05ffb50dac442572a

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

View File

@ -0,0 +1 @@
7c464fc07c731c74abbc8291583a205d

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

View File

@ -0,0 +1 @@
de5dd568e4fd9931381d45c85ae1735a

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -0,0 +1 @@
86bf2315bbfbc55772c532fb68d1de00

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -0,0 +1 @@
de6bbeb59e7f968b70fba8fc6cd72488

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

View File

@ -0,0 +1 @@
79ae40ee77e2be2b1b3487299c015919

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -0,0 +1 @@
f3af942d08fb6dc05ffb50dac442572a

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

View File

@ -0,0 +1 @@
7c464fc07c731c74abbc8291583a205d

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@ -0,0 +1 @@
de5dd568e4fd9931381d45c85ae1735a

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1 @@
86bf2315bbfbc55772c532fb68d1de00

View File

@ -0,0 +1,22 @@
---
aliases:
tags:
- maturity/🌱
date: 2024-10-02
zero-link:
parents:
linked:
---
***
## Мета информация
**Область**::
**Родитель**::
**Источник**::
**Создана**:: [[2024-10-02]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -0,0 +1,14 @@
---
tags:
- type/people
date: "[[2024-10-02]]"
---
**Work**::
**Position**::
**Создана**:: [[2024-10-02]]
**Telegram**::
## Упоминается в заметках
<!-- QueryToSerialize: LIST FROM [[]] -->
<!-- SerializedQuery: LIST FROM [[]] -->
- [[Доклад. Могут ли Virtual threads заменить Webflux]]
<!-- SerializedQuery END -->

View File

@ -0,0 +1,14 @@
---
tags:
- type/people
date: "[[2024-10-02]]"
---
**Work**::
**Position**::
**Создана**:: [[{date}]]
**Telegram**::
## Упоминается в заметках
<!-- QueryToSerialize: LIST FROM [[]] -->
<!-- SerializedQuery: LIST FROM [[]] -->
- [[Супрахиазматическое ядро]]
<!-- SerializedQuery END -->

View File

@ -36,7 +36,7 @@ title: Java разработка
- [Java 12](Java%2012.md)
- [[Java 15]]
- [[Java 17 LTS]]
- [[Java 21 LTS]]
- [[../../dev/java/Java 21 LTS|Java 21 LTS]]
## Дополнительно
- [Нативные сборки в Java](../../dev/java/Нативные%20сборки%20в%20Java.md)

View File

@ -0,0 +1,14 @@
---
tags:
- type/zero-link
date: 2024-10-02
---
Здесь собраны ссылки на заметки, в которых я анализирую прочитанный/просмотренный материал.
## Доклады
<!-- QueryToSerialize: LIST FROM #type/source/lecture SORT Создана DESC -->
<!-- SerializedQuery: LIST FROM #type/source/lecture SORT Создана DESC -->
- [[Доклад. Могут ли Virtual threads заменить Webflux]]
- [[Доклад]]
<!-- SerializedQuery END -->
## Статьи
<!-- QueryToSerialize: LIST FROM #type/source/article SORT Создана DESC -->

View File

@ -0,0 +1,27 @@
---
aliases:
date: 2024-10-02
zero-link:
parents:
linked:
---
**Организатор**:: [[../../meta/organizations/Т-Банк|Т-Банк]]
## Доклады
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Конференция, this.file.link) -->
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Конференция, this.file.link) -->
- [[Доклад. Могут ли Virtual threads заменить Webflux]]
<!-- SerializedQuery END -->
***
## Мета информация
**Область**::
**Родитель**:: [[../../meta/organizations/Т-Банк|Т-Банк]]
**Источник**::
**Создана**:: [[2024-10-02]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -0,0 +1,105 @@
---
aliases:
tags:
- maturity/🌱
- type/source/lecture
date: 2024-10-02
zero-link:
parents:
linked:
---
**Организатор**:: [[../../meta/organizations/Т-Банк|Т-Банк]]
**Конференция**:: [[../conference/Конференция. JVM Day 2024|Конференция. JVM Day 2024]]
**Автор**:: [[../../meta/people/Сергей Петрелевич|Сергей Петрелевич]]
**Ссылка::** [Могут ли Virtual threads заменить Webflux? — Сергей Петрелевич, Squad - YouTube](https://www.youtube.com/watch?v=SOvzg-uoVco)
***
**О чем доклад:** Автор пытается понять есть ли место реактивной парадигме в современной Java, после выхода [[../../dev/java/Java Virtual Threads|виртуальных потоков]]. Для этого он проводит нагрузочное тестирование и сравнивает результаты.
## Тезисы
- Прикладным разработчикам удобнее работать с абстракциями высшего порядка (Spring WebFlux, Quarkus Reactive).
- Реактивный подход остается актуальным в некоторых задачах. Архитектору как и прежде необходимо выбирать подходящий инструмент для конкретной задачи.
- Виртуальные потоки могут дать существенный прирост (в 2 раза) производительности существующему приложению.
- Виртуальные потоки легко включить, от разработчика не требуется переписывать существующий код.
- Реактивный подход (Spring WebFlux) позволит дать максимальный прирост производительности (в 3.8 раза), но за это придется заплатить.
- [[../../../../knowledge/dev/Реактивное программирование|Реактивное программирование]] требует от разработчика изучение новой парадигмы и новых подходов: "функциональный" стиль разработки (Fluent API).
***
## Конспект
Автор считает, что Java не самый эффективный язык программирования с точки зрения потребления ресурсов
Имеется куча вариантов оптимизации, которые автор предлагает рассмотреть. Рассматривать начинаем с двух концепций
- [[../../dev/architecture/Один клиент — один поток|Один клиент — один поток]]
- С таким подходов в Java быстро доходим до пределов количества потоков, которые возможно создать
- Применим, если нагрузка на систему не большая
- [[../../dev/architecture/Много клиентов — один поток|Много клиентов — один поток]]
- Кажется, что это то что надо, но это не всегда так
Автор рассматривает [[../../dev/architecture/Event Loop|Event Loop]]. Реализация в Java: NIO Selector.
Можно работать напрямую с NIO, но прикладным разработчикам удобнее работать с Netty, который позволяет работать с более высокоуровневыми абстракциям, при этом сохраняя все преимущества NIO. Но есть еще более высокоуровневая абстракция поверх Netty.
NIO посылает события Netty их преобразовывает в более удобный вид. Далее можно сделать [[../../../../_inbox/Callback|Callback-и]], на основе этого работает Vert.x. Второй подход это использовать реактивный API: Reactor Netty. Именно этот подход автор и будет рассматривать.
![[../../meta/files/images/Pasted image 20241003080932.png]]
Можно реализовывать свои приложения сразу на Reactor Netty, но еще удобнее использовать Spring Webflux. Это реактивный функциональный (позволяет разрабатывать в функциональном стиле) http-сервер, который эффективно использует ресурсы.
Пример "функционального" подхода. Fluent API
![[../../meta/files/images/Pasted image 20241003081345.png]]
Теперь рассмотрим [[../../dev/java/Java Virtual Threads|виртуальные потоки]], которые появились в Java 21. Один платформенный поток Java может работать со множеством клиентов одновременно. По сути виртуальный поток это объект класса, который выполняется на базе платформенного потока, который в свою очередь является фактически [[../../dev/fundamental/Поток процесса ОС|потоком ОС]].
![[../../../../garden/ru/meta/files/images/Pasted image 20241003081726.png]]
Виртуальный поток помогает с операциями, где есть [[../../dev/architecture/Блокирующий вызов|блокирующие операции]], где нужно "подождать". В таком случае ожидание практически ничего не стоит, так как виртуальный поток на это время блокируется и уступает платформенный поток другому виртуальному потоку. Но если вам нужно что-то считать, если у вас какие-то тяжелые CPU задачи, то виртуальные потоки вам не подходят.
Для работы с виртуальными потоками в SpingBoot достаточно включить одну проперти.
Примеры: [jvm-digging/virtual-thread at master · petrelevich/jvm-digging · GitHub](https://github.com/petrelevich/jvm-digging/tree/master/virtual-thread)
Итого, Sping WebFlux позволял нам обрабатывать множество запросов на одном потоке. И виртуальные потоки нам позволяют делать по сути то же самое. При этом не нужно разбираться в реактивной парадигме разработки. Тогда зачем нам WebFlux?
## Сравнение производительности
Для этого сравним два подхода на примере [небольшого приложения](https://github.com/petrelevich/jvm-digging/tree/master/virtual-thread), которое будет принимать REST запросы и отправлять их в кафку, после чего отвечать клиенту что сообщение доставлено.
![[../../meta/files/images/Pasted image 20241003083724.png]]
![[../../meta/files/images/Pasted image 20241003083758.png]]
Сравнение производительности. Генератор нагрузки: https://github.com/rakyll/hey
```
/hey -n=1000000 -C=300
```
- 300 клиентов отправляют 1000000 запросов
- Ethernet 1000 Mb/s
- Запускаем в докере: 256 Mb, 1 cpu.
- [[../../dev/java/gc/Garbage Collector|Garbage Collector]]: G1
- Прогрев: два запуска
- Измерений: 7
- Стандартное отклонение: 3,8; 3,7; 2,6
![[../../meta/files/images/Pasted image 20241003084259.png|500]]
Прирост производительности: 200% Virtual Thread по сравнению с платформенными потоками, а если переключиться на Webflux, то мы получим **поверх** еще 30%.
Переход на Virtual Thread максимально прост, при этом максимально эффективен. Поэтому особого смысла переписывать старые приложения на рекативной подход нет, проще включить виртуальные потоки.
### Причины
Почему Webflux производительней виртуальных потоков?
- Может быть, где-то в коде есть synchronized? События jdk.VirtualThreadPinned не фиксируются
- Замедление, наиболее вероятно, связано с переключением на платформенные потоки. JMC показывает множество событий: jdk.VirtualThreadStart, jdk.VirtualThreadEnd. При этом их длительность 0 (WTF?).
## Дополнительные материалы
-
***
## Мета информация
**Область**::
**Родитель**::
**Источник**::
**Создана**:: [[2024-10-02]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->