Рубрики
Без рубрики

Сравнение встроенных контейнеров сервлетов в Spring Boot

Посмотрите, как поддерживаемые контейнеры сервлетов Spring Boot сравниваются друг с другом.

Автор оригинала: Chris Oberle.

1. введение

Растущая популярность облачных приложений и микросервисов порождает повышенный спрос на встроенные контейнеры сервлетов. Spring Boot позволяет разработчикам легко создавать приложения или службы, используя 3 самых зрелых доступных контейнера: Tomcat, Undertow и Jetty.

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

2. Зависимости

Наша настройка для каждой доступной реализации контейнера всегда потребует, чтобы мы объявили зависимость от spring-boot-starter-web в нашем pom.xml .

В общем, мы хотим указать нашего родителя как spring-boot-starter-parent , а затем включить нужные нам стартеры:


    org.springframework.boot
    spring-boot-starter-parent
    2.4.0
    



    
        org.springframework.boot
        spring-boot-starter
    

    
        org.springframework.boot
        spring-boot-starter-web
    

2.1. Кот

Дополнительные зависимости не требуются при использовании Tomcat, поскольку он включен по умолчанию при использовании spring-boot-starter-web .

2.2. Причал

Чтобы использовать Jetty, нам сначала нужно исключить spring-boot-starter-tomcat из spring-boot-starter-web .

Затем мы просто объявляем зависимость от spring-boot-starter-jetty :


    org.springframework.boot
    spring-boot-starter-web
    
        
            org.springframework.boot
            spring-boot-starter-tomcat
        
    


    org.springframework.boot
    spring-boot-starter-jetty

2.3. Подводное течение

Настройка для Undertow идентична Jetty, за исключением того, что мы используем spring-boot-starter-undertow в качестве нашей зависимости:


    org.springframework.boot
    spring-boot-starter-web
    
        
            org.springframework.boot
            spring-boot-starter-tomcat
        
    


    org.springframework.boot
    spring-boot-starter-undertow

2.4. Привод

Мы будем использовать привод Spring Boot как удобный способ как подчеркнуть систему, так и запросить метрики.

Проверьте эту статью для получения подробной информации о приводе. Мы просто добавляем зависимость в ваш pom , чтобы сделать ее доступной:


    org.springframework.boot
    spring-boot-starter-actuator

2.5. ApacheBench

Apache Bench – это утилита нагрузочного тестирования с открытым исходным кодом, которая поставляется в комплекте с веб-сервером Apache.

Пользователи Windows могут загрузить Apache от одного из сторонних поставщиков, связанных здесь . Если Apache уже установлен на вашем компьютере с Windows, вы сможете найти ab.exe в вашем каталоге apache/bin .

Если вы находитесь на машине Linux, ab можно установить с помощью apt-get с помощью:

$ apt-get install apache2-utils

3. Показатели запуска

3.1. Сбор

Чтобы собрать наши показатели запуска, мы зарегистрируем обработчик событий для запуска в ApplicationReadyEvent Spring Boot .

Мы будем программно извлекать интересующие нас показатели, непосредственно работая с реестром Meter , используемым компонентом привода:

@Component
public class StartupEventHandler {

    // logger, constructor
    
    private String[] METRICS = {
      "jvm.memory.used", 
      "jvm.classes.loaded", 
      "jvm.threads.live"};
    private String METRIC_MSG_FORMAT = "Startup Metric >> {}={}";
    
    private MeterRegistry meterRegistry;

    @EventListener
    public void getAndLogStartupMetrics(
      ApplicationReadyEvent event) {
        Arrays.asList(METRICS)
          .forEach(this::getAndLogActuatorMetric);
    }

    private void processMetric(String metric) {
        Meter meter = meterRegistry.find(metric).meter();
        Map stats = getSamples(meter);
 
        logger.info(METRIC_MSG_FORMAT, metric, stats.get(Statistic.VALUE).longValue());
    }

    // other methods
}

Мы избегаем необходимости вручную запрашивать конечные точки REST привода или запускать автономную консоль JMX, регистрируя интересные показатели при запуске в нашем обработчике событий.

3.2. Выбор

Существует большое количество показателей, которые Привод предоставляет из коробки. Мы выбрали 3 метрики, которые помогают получить высокоуровневый обзор ключевых характеристик среды выполнения после запуска сервера:

  • jvm.memory.used – общая память, используемая JVM с момента запуска
  • jvm.classes.loaded – общее количество загруженных классов
  • jvm.потоки.live – общее количество активных потоков. В нашем тесте это значение можно рассматривать как количество потоков “в состоянии покоя”

4. Показатели времени выполнения

4.1. Сбор

В дополнение к предоставлению метрик запуска, мы будем использовать конечную точку /metrics , предоставленную исполнителем, в качестве целевого URL-адреса при запуске Apache Bench, чтобы загрузить приложение.

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

Как только сервер запустится, мы получим командную строку и выполним ab :

ab -n 10000 -c 10 http://localhost:8080/actuator/metrics

В приведенной выше команде мы указали в общей сложности 10 000 запросов, использующих 10 параллельных потоков.

4.2. Выбор

ApacheBench способен очень быстро предоставить нам некоторую полезную информацию, включая время подключения и процент запросов, которые обслуживаются в течение определенного времени.

Для наших целей мы сосредоточились на запросах в секунду и времени на запрос (среднее значение).

5. Результаты

При запуске мы обнаружили, что объем памяти Tomcat, Jetty и Undertow был сопоставим с Undertow, требующим немного больше памяти, чем два других, а Jetty требует наименьшего объема.

Для нашего бенчмарка мы обнаружили, что производительность Tomcat, Jetty и Undertow была сопоставима но что Undertow был явно самым быстрым, а Jetty лишь немного менее быстрым.

155.000 jvm.memory.used (МБ) 168.000 164.000
9784.000 jvm.memory.used (МБ) 9869.000 9787.000
17.000 jvm.memory.used (МБ) 25.000 19.000
1627.000 Запросы в секунду 1542.000 1650.000
6.148 Среднее время на запрос (мс) 6.483 6.059

Обратите внимание, что метрики, естественно, являются репрезентативными для проекта “голые кости”; метрики вашего собственного приложения, безусловно, будут отличаться.

6. Обсуждение контрольных показателей

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

Важно отметить, что контрольные измерения, собранные в этом примере, были выполнены с использованием очень специфической рабочей нагрузки, состоящей из запросов HTTP GET к конечной точке Привода.

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

Кроме того, более сложное решение для бенчмаркинга, такое как JMeter или Gatling, скорее всего, даст более ценную информацию.

7. Выбор контейнера

Выбор правильной реализации контейнера, вероятно, должен основываться на многих факторах, которые не могут быть аккуратно суммированы только с помощью нескольких метрик . Уровень комфорта, функции, доступные параметры конфигурации и политика часто одинаково важны, если не более того.

8. Заключение

В этой статье мы рассмотрели реализации контейнеров встроенных сервлетов Tomcat, Jetty и Undertow. Мы изучили характеристики времени выполнения каждого контейнера при запуске с конфигурациями по умолчанию, рассмотрев показатели, предоставляемые компонентом привода.

Мы выполнили надуманную рабочую нагрузку на работающую систему, а затем измерили производительность с помощью Apache Bench.

Наконец, мы обсудили достоинства этой стратегии и упомянули несколько вещей, которые следует иметь в виду при сравнении контрольных показателей реализации. Как всегда, весь исходный код можно найти на GitHub .