1. 소개

 
클라우드 네이티브 애플리케이션과 마이크로 서비스의 인기가 높아지면서 임베디드 서블릿 컨테이너에 대한 수요가 증가하고 있습니다. Spring Boot를 사용하면 개발자가 Tomcat, Undertow 및 Jetty라는 가장 성숙한 3 개의 컨테이너를 사용하여 애플리케이션 또는 서비스를 쉽게 빌드 할 수 있습니다.이 사용방법(예제)에서는 시작 및 일부 부하에서 얻은 메트릭을 사용하여 컨테이너 구현을 빠르게 비교하는 방법을 보여줍니다.

2. 의존성

 
사용 가능한 각 컨테이너 구현에 대한 설정은 항상 pom.xml 에서

spring-boot-starter-web

에 대한 의존성을 선언해야합니다 .일반적으로 부모를

spring-boot-starter-parent

로 지정한 다음 원하는 스타터를 포함합니다.
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.0</version>
    <relativePath/>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

2.1. Tomcat

 

Spring-boot-starter-web을

사용할 때 기본적으로 포함되므로 Tomcat을 사용할 때 추가 의존성이 필요하지 않습니다 .

2.2. Jetty

 
Jetty를 사용하려면 먼저 spring-boot-starter-web 에서 spring-boot-starter-

tomcat

을 제외해야합니다 .그런 다음 단순히

spring-boot-starter-jetty

에 대한 의존성을 선언합니다 .
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

2.3. Undertow

 
Undertow 설정은

Spring-boot-starter-undertow

를 의존성으로 사용한다는 점을 제외하면 Jetty와 동일합니다 .
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

2.4. 액추에이터

 
시스템에 스트레스를주고 메트릭에 대한 쿼리를 수행하는 편리한 방법으로 Spring Boot의 Actuator를 사용할 것입니다.액추에이터에 대한 자세한 내용은

이 문서

확인하십시오  . 단순히

pom

의존성을 추가하여 사용할 수 있도록합니다.
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

 2.5. Apache 벤치

 

Apache Bench

 는 Apache 웹 서버와 함께 제공되는 오픈 소스 부하 테스트 유틸리티입니다.Windows 사용자는

여기에

링크 된 타사 공급 업체 중 하나에서 Apache를 다운로드 할 수 있습니다 . Windows 시스템에 Apache가 이미 설치되어있는 경우 apache / bin 디렉토리 에서

ab.exe

를 찾을 수 있습니다 .Linux 시스템을 사용하는 경우 다음 과 함께 apt-get사용하여

ab

를 설치할 수 있습니다 .
$ apt-get install apache2-utils

3. 시작 메트릭

 

3.1. 수집

 
시작 메트릭을 수집하기 위해 Spring Boot의

ApplicationReadyEvent

에서 실행할 이벤트 핸들러를 등록합니다 .Actuator 구성 요소에서 사용 하는

MeterRegistry

를 직접 사용하여 관심있는 메트릭을 프로그래밍 방식으로 추출합니다 .
@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<Statistic, Double> stats = getSamples(meter);
 
        logger.info(METRIC_MSG_FORMAT, metric, stats.get(Statistic.VALUE).longValue());
    }

    // other methods
}
Actuator REST 엔드 포인트를 수동으로 쿼리하거나 이벤트 핸들러 내에서 시작시 흥미로운 메트릭을 로깅하여 독립형 JMX 콘솔을 실행할 필요가 없습니다.

3.2. 선택

 
Actuator가 기본적으로 제공하는 많은 메트릭이 있습니다. 서버가 가동되면 주요 런타임 특성에 대한 높은 수준의 개요를 얻는 데 도움이되는 3 가지 메트릭을 선택했습니다.
  • jvm.memory.used – 시작 이후 JVM에서 사용한 총 메모리
  • jvm.classes.loaded –로드 된 총 클래스 수
  • jvm.threads.live – 총 활성 스레드 수입니다. 테스트에서이 값은 "휴지 상태"의 스레드 수로 볼 수 있습니다.

4. 런타임 메트릭

 

4.1. 수집

 
시작 메트릭을 제공하는 것 외에도 Apache Bench를 실행할 때 Actuator에서 노출 하는

/ metrics 

엔드 포인트를 대상 URL로 사용하여 애플리케이션을로드합니다.부하가 걸린 실제 애플리케이션을 테스트하기 위해 대신 애플리케이션에서 제공하는 엔드 포인트를 사용할 수 있습니다.서버가 시작되면 명령 프롬프트가 표시되고

ab를

실행합니다 .
ab -n 10000 -c 10 http://localhost:8080/actuator/metrics
위의 명령에서 10 개의 동시 스레드를 사용하여 총 10,000 개의 요청을 지정했습니다.

4.2. 선택

 
Apache Bench는 연결 시간 및 특정 시간 내에 제공되는 요청 비율을 포함하여 유용한 정보를 매우 빠르게 제공 할 수 있습니다.우리의 목적을 위해

초당 요청 및 요청 당 시간 (평균)에 중점을 두었습니다.

5. 결과

 
시작시

Tomcat, Jetty 및 Undertow의 메모리 풋 프린트

는 다른 두 개보다 약간 더 많은 메모리를 필요로하는 Undertow 및 가장 적은 양을 필요로하는 Jetty와 비슷 하다는 것을 발견했습니다 .벤치 마크

의 경우 Tomcat, Jetty 및 Undertow의 성능이 비슷

하지만 Undertow가 분명히 가장 빠르고 Jetty가 약간 느리다는 것을 발견했습니다

미터법 Tomcat Jetty Undertow
jvm.memory.used (MB) 168 155 164
jvm.classes.loaded 9869 9784 9787
jvm.threads.live 25 17 19
초당 요청 1542 년 1627 년 1650 년
요청 당 평균 시간 (밀리 초) 6.483 6.148 6.059
메트릭은 당연히 베어 본 프로젝트를 대표합니다. 자신의 응용 프로그램의 메트릭은 확실히 다를 것입니다.

6. 벤치 마크 토론

 
서버 구현을 철저히 비교하기 위해 적절한 벤치 마크 테스트를 개발하는 것은 복잡 할 수 있습니다. 가장 관련성이 높은 정보를 추출하려면 해당

사용 사례에서 무엇이 중요한지 명확하게 이해하는 것이 중요합니다

.이 예제에서 수집 된 벤치 마크 측정은 Actuator 엔드 포인트에 대한 HTTP GET 요청으로 구성된 매우 구체적인 워크로드를 사용하여 수행되었습니다.

서로 다른 워크로드는 컨테이너 구현 전반에 걸쳐 서로 다른 상대적 측정 결과를 초래할 것으로 예상됩니다

. 더 견고하거나 정확한 측정이 필요한 경우 프로덕션 사용 사례와 더 근접하게 일치하는 테스트 계획을 설정하는 것이 좋습니다.또한

JMeter

또는

Gatling

과 같은보다 정교한 벤치마킹 솔루션 은 더 가치있는 통찰력을 얻을 수 있습니다.

7. 컨테이너 선택

 

적절한 컨테이너 구현을 선택하려면 몇 가지 측정 항목만으로는 깔끔하게 요약 할 수없는 여러 요소를 기반으로해야합니다

. 편안함 수준, 기능, 사용 가능한 구성 옵션 및 정책은 그 이상은 아니지만 똑같이 중요합니다.

8. 결론

 
이 기사에서는 Tomcat, Jetty 및 Undertow 임베디드 서블릿 컨테이너 구현을 살펴 보았습니다. Actuator 구성 요소에 의해 노출 된 메트릭을 살펴Spring으로써 기본 구성으로 시작시 각 컨테이너의 런타임 특성을 조사했습니다.실행중인 시스템에 대해 인위적인 워크로드를 실행 한 다음 Apache Bench를 사용하여 성능을 측정했습니다.마지막으로이 전략의 장점에 대해 논의하고 구현 벤치 마크를 비교할 때 유의해야 할 몇 가지 사항을 언급했습니다. 항상 그렇듯이 모든 소스 코드는

GitHub

에서 찾을 수 있습니다 .