Vergleichen eingebetteter Servlet-Container in Spring Boot

Vergleichen von Embedded Servlet Containern im Spring Boot

1. Einführung

Die zunehmende Popularität von Cloud-nativen Anwendungen und Mikrodiensten führt zu einer erhöhten Nachfrage nach eingebetteten Servlet-Containern. Mit Spring Boot können Entwickler auf einfache Weise Anwendungen oder Dienste mit den drei ausgereiftesten verfügbaren Containern erstellen: Tomcat, Undertow und Jetty.

In diesem Tutorial zeigen wir Ihnen, wie Sie Containerimplementierungen schnell mit Metriken vergleichen können, die beim Start und unter Last erhalten wurden.

2. Abhängigkeiten

Unser Setup für jede verfügbare Container-Implementierung erfordert immer, dass wir in unserenpom.xml eine Abhängigkeit vonspring-boot-starter-web deklarieren.

Im Allgemeinen möchten wir unser übergeordnetes Element alsspring-boot-starter-parent angeben und dann die gewünschten Starter einschließen:


    org.springframework.boot
    spring-boot-starter-parent
    2.0.3.RELEASE
    



    
        org.springframework.boot
        spring-boot-starter
    

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

2.1. Kater

Bei Verwendung von Tomcat sind keine weiteren Abhängigkeiten erforderlich, da diese bei Verwendung vonspring-boot-starter-web standardmäßig enthalten sind.

2.2. Anlegesteg

Um Jetty verwenden zu können, müssen wir zuerstspring-boot-starter-tomcat vonspring-boot-starter-web ausschließen.

Dann deklarieren wir einfach eine Abhängigkeit vonspring-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. Sog

Das Einrichten für Undertow ist identisch mit Jetty, außer dass wirspring-boot-starter-undertow als unsere Abhängigkeit verwenden:


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


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

2.4. Aktuator

Wir werden den Aktuator von Spring Boot verwenden, um das System zu belasten und Metriken abzufragen.

Weitere Informationen zum Aktuator finden Sie unterthis article. Wir fügen einfach eine Abhängigkeit in unserepom ein, um sie verfügbar zu machen:


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

 2.5. Apache-Bank

Apache Bench ist ein Open Source-Dienstprogramm zum Testen der Last, das im Lieferumfang des Apache-Webservers enthalten ist.

Windows-Benutzer können Apache von einem der Drittanbieter herunterladen, diehere verknüpft haben. Wenn Apache bereits auf Ihrem Windows-Computer installiert ist, sollten Sieab.exe in Ihremapache/bin-Verzeichnis finden können.

Wenn Sie sich auf einem Linux-Computer befinden, könnenab mitapt-get installiert werden mit:

$ apt-get install apache2-utils

3. Startmetriken

3.1. Sammlung

Um unsere Startmetriken zu erfassen, registrieren wir einen Ereignishandler, der aufApplicationReadyEventvon Spring Boot ausgelöst wird.

Wir extrahieren programmgesteuert die Metriken, an denen wir interessiert sind, indem wir direkt mit denMeterRegistryarbeiten, die von der Actuator-Komponente verwendet werden:

@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
}

Wir vermeiden die Notwendigkeit, REST-Endpunkte von Actuator manuell abzufragen oder eine eigenständige JMX-Konsole auszuführen, indem wir interessante Messdaten beim Start in unserem Event-Handler protokollieren.

3.2. Auswahl

Es gibt eine große Anzahl von Metriken, die von Actuator standardmäßig bereitgestellt werden. Wir haben drei Metriken ausgewählt, mit denen Sie einen umfassenden Überblick über die wichtigsten Laufzeitmerkmale erhalten, sobald der Server hochgefahren ist:

  • jvm.memory.used - Der Gesamtspeicher, der von der JVM seit dem Start verwendet wird

  • jvm.classes.loaded - die Gesamtzahl der geladenen Klassen

  • jvm.threads.live - die Gesamtzahl der aktiven Threads. In unserem Test kann dieser Wert als Fadenzahl im Ruhezustand angesehen werden.

4. Laufzeitmetriken

4.1. Sammlung

Zusätzlich zur Bereitstellung von Startmetriken verwenden wir den vom Actuator bereitgestellten/metrics -Sendpunkt als Ziel-URL, wenn wir Apache Bench ausführen, um die Anwendung unter Last zu setzen.

Um eine echte Anwendung unter Last zu testen, können wir stattdessen Endpunkte verwenden, die von unserer Anwendung bereitgestellt werden.

Sobald der Server gestartet wurde, erhalten wir eine Eingabeaufforderung und führenab aus:

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

Im obigen Befehl haben wir insgesamt 10.000 Anforderungen mit 10 gleichzeitigen Threads angegeben.

4.2. Auswahl

Apache Bench kann uns sehr schnell nützliche Informationen geben, einschließlich der Verbindungszeiten und des Prozentsatzes der Anfragen, die innerhalb einer bestimmten Zeit bearbeitet werden.

Für unsere Zweckewe focused on requests-per-second and time-per-request (mean).

5. Ergebnisse

Beim Start haben wir festgestellt, dassthe memory footprint of Tomcat, Jetty, and Undertow was comparable mit Undertow etwas mehr Speicher benötigt als die beiden anderen und Jetty die geringste Menge benötigt.

Für unsere Benchmark haben wirthe performance of Tomcat, Jetty, and Undertow was comparable, aberUndertow was clearly the fastest and Jetty only slightly less fast.  gefunden

Metrisch

Kater

Anlegesteg

Sog

jvm.memory.used (MB)

168

155

164

jvm.classes.loaded

9869

9784

9787

jvm.threads.live

25

17

19

Anfragen pro Sekunde

1542

1627

1650

Durchschnittliche Zeit pro Anfrage (ms)

6.483

6.148

6.059

Beachten Sie, dass die Metriken natürlich repräsentativ für das Bare-Bones-Projekt sind. Die Metriken Ihrer eigenen Anwendung werden mit Sicherheit anders sein.

6. Benchmark-Diskussion

Die Entwicklung geeigneter Benchmark-Tests zum Durchführen gründlicher Vergleiche von Serverimplementierungen kann kompliziert werden. Um die relevantesten Informationen zu extrahieren, wirdit’s critical to have a clear understanding of what’s important for the use case in question.

Es ist wichtig zu beachten, dass die in diesem Beispiel gesammelten Benchmark-Messungen unter Verwendung einer sehr spezifischen Arbeitslast durchgeführt wurden, die aus HTTP-GET-Anforderungen an einen Actuator-Endpunkt besteht.

It’s expected that different workloads would likely result in different relative measurements across container implementations. Wenn robustere oder genauere Messungen erforderlich wären, wäre es eine sehr gute Idee, einen Testplan aufzustellen, der dem Anwendungsfall in der Produktion besser entspricht.

Darüber hinaus würde eine ausgefeiltere Benchmarking-Lösung wieJMeter oderGatling wahrscheinlich wertvollere Erkenntnisse liefern.

7. Container auswählen

Selecting the right container implementation should likely be based on many factors that can’t be neatly summarized with a handful of metrics alone. Komfort, Funktionen, verfügbare Konfigurationsoptionen und Richtlinien sind oft gleich wichtig, wenn nicht sogar wichtiger.

8. Fazit

In diesem Artikel haben wir uns die Embedded-Servlet-Container-Implementierungen von Tomcat, Jetty und Undertow angesehen. Wir haben die Laufzeitmerkmale jedes Containers beim Start mit den Standardkonfigurationen untersucht, indem wir uns die von der Actuator-Komponente bereitgestellten Metriken angesehen haben.

Wir haben eine erfundene Arbeitslast auf dem laufenden System ausgeführt und dann die Leistung mit Apache Bench gemessen.

Zuletzt haben wir die Vorzüge dieser Strategie erörtert und einige Punkte erwähnt, die beim Vergleich der Implementierungs-Benchmarks zu beachten sind. Wie immer kann der gesamte Quellcodeover on GitHub gefunden werden.