Тест производительности Reactive vs Synch с помощью Spring Boot

Reactive — это парадигма программирования, использующая асинхронное программирование. Она наследует эффективность параллелизма асинхронной модели с простотой использования декларативного программирования.

Многопоточность позволяет распараллелить работу на нескольких процессорах, но когда выполняется операция ввода-вывода, поток блокируется в ожидании завершения ввода-вывода.

Reactive/Async не распараллеливает работу на нескольких процессорах, но когда выполняется операция ввода-вывода, процессор передается следующей задаче в цикле событий.

Как правило, использование нескольких процессов или потоков лучше для систем с ограниченным процессором, а async/reactive — для систем с ограниченным вводом-выводом.

ПРИМЕЧАНИЕ: Это модифицированный репост теста, проведенного в 2018 году. Фото Andrew Wulf on Unsplash

Более простое асинхронное программирование

Давайте рассмотрим пример метода, который извлекает пользователя из базы данных, выполняет некоторые преобразования, трансформации и затем выводит результаты.

Синхронная версия выглядит следующим образом:

User user = getUserFromDBSync(id);
user = convertUser(user);
user = processResult(user);
displayResults(user);
Вход в полноэкранный режим Выход из полноэкранного режима

Довольно просто.

Асинхронная версия с обратными вызовами имеет глубоко вложенный код, по сути, «ад обратных вызовов».

getUserFromDB(id, user -> {
  convertUser(user, convertedUser -> {
    processResult(convertedUser, processedUser -> {
      displayResults(processedUser);
    });
  });
});
Войти в полноэкранный режим Выход из полноэкранного режима

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

getUserFromDBAsync(id)
  .map(user -> convertUser(user))
  .map(user -> processResult(user))
  .subscribe(user -> displayResults(user));
Вход в полноэкранный режим Выход из полноэкранного режима

Улучшенная многозадачность

Что касается параллелизма, я решил провести небольшой тест, чтобы оценить разницу между реактивной и синхронной версией для операций, связанных с IO.

Вы можете получить тестовый проект здесь https://github.com/trincaog/reactivetest.

Тест настроен следующим образом:

  • Клиент нагрузочного тестирования (Gatling)
  • Тестовый сервис (Spring Boot)
  • Внешний бэкенд-сервис (симулированный)

Тестовый бэкенд-сервис

Тестовый бэкенд-сервис имитирует запрос к внешнему сервису (например, базе данных), которому требуется некоторое время, чтобы вернуть список записей. Для упрощения тест не отправляет запрос к реальной базе данных, вместо этого он имитирует задержку ответа.

Настройка синхронной версии:

  • Приложение Spring Boot 2.0 (2.0.0.RC1) / фреймворк Spring MVC.
  • Встроенный контейнер Tomcat с max threads=10.000 (большое число, чтобы избежать очереди запросов).
  • Хостинг на AWS ECS/Fargate с 256 mCPU / 2GB RAM

Установка реактивной версии:

  • Приложение Spring Boot 2.0 (2.0.0.RC1) / фреймворк Spring Webflux
  • фреймворк Netty
  • Размещено на AWS ECS/Fargate с 256 mCPU / 2GB RAM

Клиент нагрузочного тестирования

Использовались следующие компоненты:

  • AWS EC2 t2.small 1vCPU / 2GB RAM
  • Gatling 2.3.0
  • Непрерывный цикл запросов без каких-либо задержек между запросами
  • 2 конфигурации внешнего сервиса: одна с временем отклика 500 мс; другая с временем отклика 2.000 мс.

Нагрузочный тест #1: Задержка внешнего сервиса 500 мс

При <=100 одновременных запросах время ответа очень похоже между двумя версиями.

После 200 одновременных пользователей версия synchronous/tomcat начинает ухудшать время отклика, в то время как реактивная версия с Netty держится до 2.000 одновременных пользователей.

Нагрузочный тест №2: Задержка внешней службы 2.000 мс

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

В этом тесте синхронная версия начинает ухудшаться при 4-5-кратном количестве одновременных пользователей, чем в предыдущем тесте с задержкой 500 мс.

Оцените статью
devanswers.ru
Добавить комментарий