Исследование объёма используемых ресурсов и стабильности приложения при переходе на реактивные компоненты в случае увеличения времени ответа от внешних источников данных
Введение 3
Постановка задачи 5
1. Реактивный подход к программированию 6
1.1. Синхронный подход к программированию 6
1.2. Концепция реактивного программирования 8
1.3. Способы написания кода в реактивном стиле в Java и Kotlin 9
1.4. Реактивные компоненты и драйверы баз данных 11
2. Тестовый стенд для нагрузочного тестирования 13
2.1. Архитектура тестового стенда для нагрузочного тестирования 13
2.2. Ресурсы и изолированость тестовой среды 14
2.3. Тестируемое приложение 16
2.4. Нагрузочное приложение 17
2.5. Сбор и визуализация метрик 19
3. Проведение экспериментов 21
3.1. Рассматриваемые метрики 21
3.2. Обращение к внешнему сервису 22
3.3. Обращение к базе данных 25
3.4. Обработка записей из базы данных 30
3.5. Обработка записей из базы данных внешним сервисом . . . 35
3.6. Выводы 38
Заключение 40
Список литературы 41
Реактивное программирование как идея появилось ещё в двадцатом веке. Однако, долгое время рост производительности систем происходил в первую очередь за счёт роста производительности процессоров. Но в конце 2000-х годов этот рост сильно замедлился, из-за чего фокус внимания в области улучшения производительности систем был вновь обращён на асинхронное и реактивное программирование, как на способ улучшить производительность систем при использовании тех же ресурсов.
Традиционный (синхронный) подход к программированию представляет собой набор последовательных блокирующих операций и вызовов внешних систем (например, обращений к базам данных или вызовов сторонних сервисов). Такой подход зачастую может быть неэффективным из-за того, что в момент ожидания ответа от внешней системы, ресурсы вызывающей системы заблокированы и простаивают.
Одним из вариантов улучшения производительности является переход к концепции реактивного программирования. Реактивное программирование предполагает создание системы, реагирующей на изменение в данных в режиме реального времени. Такой подход подразумевает возможность начать обработку не сразу всех данных, а лишь той части, о которой системе уже известно. Например, если необходимо извлечь из базы данных большое количество записей, а затем обработать каждую из них, в традиционном подходе сначала были бы получены все записи путём запроса к базе данных, затем каждая запись была бы обработана и лишь затем результат обработки всех данных был бы подан на выход системы. В случае же использования реактивного подхода, реактивный драйвер базы данных будет подавать на вход системе обработки не сразу все записи, а последовательно те, которые уже найдены и извлечены, затем система обработки будет обрабатывать последовательно данные, получаемые от драйвера, при этом такая обработка не будет дожидаться получения всех данных, а будет реагировать на каждую новую поступающую на вход запись, а затем система будет подавать на выход обработанные данные по мере готовности.
В 2011 году компанией Microsoft был представлен первый крупный реактивный фреймворк - ReactiveX [1]. В языке программирования Java (и других JVM-языках) фреймворк получил наибольшую популярность в виде расширения RxJava после выхода 8-й версии Java в 2014-м году, поддерживающей лямбда-выражения, которые удобны для работы в реактивном стиле. В 2018-м году было представлено расширение для языка Kotlin, позволяющее использовать корутины для написания реактивного кода. Это значительно понизило порог входа для написания реактивных приложений...
В ходе работе были выполнены следующие задачи:
• Разработан изолированный тестовый стенд, а также написан код для его быстрого автоматического развёртывания и проведения нагрузочного тестирования по описанному сценарию;
• На тестовом стенде проведены эксперименты, изучающие и сравнивающие поведение нереактивной и реактивной реализации приложений в нескольких сценариях обработки запроса;
• На основе проведенных экспериментов исследованы стабильность и утилизация ресурсов приложения с реактивными компонентами и без них, в том числе при росте времени ответа внешних сервисов и источников данных;
• Получены выводы о целесообразности использования реактивных компонентов в тех или иных ситуациях, подробно описанные в разделе 3.6.