知識庫 / Spring / Spring Boot RSS 訂閱

Spring Boot 中嵌入式 Servlet 容器比較

Spring Boot
HongKong
4
01:45 PM · Dec 06 ,2025

1. 簡介

雲原生應用程序和微服務日益流行,導致嵌入式 Servlet 容器需求增加。 Spring Boot 允許開發者輕鬆使用 3 個最成熟的容器構建應用程序或服務: Tomcat、Undertow 和 Jetty。

在本教程中,我們將演示如何使用啓動時和在一定負載下獲得的指標快速比較容器實現。

2. 依賴關係

我們的每個可用容器實現配置都必須聲明對 <em >spring-boot-starter-web</em > 的依賴。

通常,我們希望將父項目設置為 spring-boot-starter-parent,然後包含我們需要的 spring-boot-starterspring-boot-starter-web 啓動器。

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.1.5</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

無需在使用 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 與 Jetty 相同,只是我們使用 spring-boot-starter-undertow 作為依賴項:

<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. Actuator

我們將使用 Spring Boot 的 Actuator 以方便的方式對系統進行壓力測試並查詢指標。

請查看這篇文章以瞭解有關 Actuator 的詳細信息。我們只需在我們的 pom 中添加一個依賴項即可使其可用:

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

2.5. Apache Bench

Apache Bench 是一個開源負載測試工具,與 Apache Web 服務器一起安裝。

Windows 用户可以從以下第三方供應商處下載 Apache:此處。 如果 Apache 已經在您的 Windows 機器上安裝,您應該可以在 apache/bin 目錄下找到 ab.exe

如果您在 Linux 機器上,可以使用 apt-get 安裝 ab,如下所示:

$ apt-get install apache2-utils

3. 啓動指標

Startup metrics are key indicators of a startup’s health and progress. They provide insights into the company’s growth, efficiency, and overall strategy. Tracking these metrics allows founders and investors to make informed decisions and adjust their approach as needed. Here are some of the most important startup metrics:

  • Monthly Recurring Revenue (MRR): This measures the predictable revenue a company generates each month from subscriptions or recurring services. It’s a critical indicator of a business’s stability and growth potential.
  • Customer Acquisition Cost (CAC): CAC represents the total cost of acquiring a new customer. It’s calculated by dividing total marketing and sales expenses by the number of new customers acquired.
  • Customer Lifetime Value (CLTV): CLTV predicts the total revenue a customer will generate throughout their relationship with the company.
  • Burn Rate: This is the rate at which a startup is spending its cash reserves. It’s calculated by dividing the monthly expenses by the remaining cash balance.
  • Churn Rate: This measures the percentage of customers who cancel their subscriptions or stop using a company’s services within a given period.

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,000 個請求,使用 10 個併發線程。

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
Requests per second 1542 1627 1650
Average time per request (ms) 6.483 6.148 6.059

請注意,這些指標代表的是一個裸項目的表現;您自己的應用程序的指標肯定會有所不同。

6. 基準討論

開發適當的基準測試,以對服務器實現進行徹底比較,可能會變得複雜。為了提取最相關的信息,必須對所涉及用例的重要性有清晰的理解

需要注意的是,本示例中收集的基準測量是在使用一個非常具體的負載下進行的,該負載包括對 Actuator 端點執行的 HTTP GET 請求。

預計不同負載將導致不同容器實現之間的相對測量值不同。如果需要更穩健或精確的測量值,則設置一個更貼近生產用例的測試計劃將是一個非常好的主意。

此外,像 JMeter 或 Gatling 這樣的更高級的基準測試解決方案可能會產生更有價值的見解。

7. 選擇容器

選擇合適的容器實現應該基於許多無法用少數指標清晰總結的因素。舒適度、功能、可用的配置選項和策略通常同樣重要,甚至更重要。

8. 結論

本文介紹了 Tomcat、Jetty 和 Undertow 這三種嵌入式 Servlet 容器的實現。通過分析 Actuator 組件暴露的指標,我們考察了每種容器的啓動時的運行時特性。

我們對運行系統執行了一個人為設計的負載測試,然後使用 Apache Bench 測量性能。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.