吊打 Tomcat ,Undertow 性能很炸!!


在 Java Web 容器的世界里,Tomcat 和 Jetty 是大名鼎鼎的、用的最多的開源項目,也是大眾熟知的。

今天再介紹另外一款能和 Tomcat 媲美的神器:Undertow,據說性能方面還要吊打 Tomcat,如果你還不知道它,那你就 OUT 了。

我們來看下 Spring Boot 默認支持的三種 Servlet 容器:

Name Servlet Version
Tomcat 9.0 4.0
Jetty 9.4 3.1
Undertow 2.0 4.0

以上來源於 Spring Boot 2.3.2 官方文檔,更多信息請點擊這里參考這篇文章。

Undertow 它能成為 Spring Boot 默認集成的三大容器之一,就憑這點,我想就足以說明它的地位。

Undertow 什么鬼?

Undertow 是 RedHat(紅帽公司)的開源產品,采用 Java 開發,是一款靈活、高性能的 Web 服務器,提供了基於 NIO 的阻塞/非阻塞 APIs,也是 Wildfly 的默認 Web 容器。

搜索 Undertow:

頁面顯示的是 JBoss Community,因為 2006 年 RedHat 收購了 JBoss,那也就不足為怪了。

Undertow 它是一個基於組合的體系結構,可以通過組合一系列小型處理器來構建一個 Web 服務器。這就讓我們可以靈活的在 Java EE servlet 4.0 容器和底層非阻塞處理器或者其他更多之間進行選擇。

Undertow 被設計成完全可嵌入式的,所以也叫嵌入式容器,具有易於使用的流暢構建 API,另外,Undertow 的生命周期也完全由所嵌入的應用程序所控制。

這也是為什么 Spring Boot 可以直接嵌入 Undertow 的原因,Undertow 它就是為了嵌入而發燒的。Spring Boot 基礎知識就不介紹了,關注公眾號Java技術棧在后台回復boot獲取我寫的系列教程。

官方網站:

https://undertow.io/

源碼托管在 Github:

https://github.com/undertow-io/undertow

Undertow 有啥特性?

1)HTTP/2 Support

Undertow 支持 HTTP/2 開箱即用,不需要重寫引導類路徑。

2)支持 HTTP 升級

支持 HTTP 升級,允許多個協議通過 HTTP 端口上進行復用。

3)支持 Web Socket

Undertow 提供對 Web 套接字的全面支持,包括對 JSR-356 的支持。

4)支持 Servlet 4.0

Undertow 提供了對 Servlet 4.0 的支持,包括對嵌入式 Servlet 的支持,還可以混合部署 Servlet 和原生 Undertow 非阻塞處理程序。

5)可嵌入式

Undertow 可以嵌入到應用程序中,也可以通過幾行代碼獨立運行。

6)高靈活性

一個 Undertow 服務器是通過鏈式處理器來配置的,可以根據需要添加功能,因此可以避免添加沒有必要的功能。

Undertow 性能如何?

國外有篇帖子做了 Tomcat vs. Jetty vs. Undertow 三者的性能比較:

https://examples.javacodegeeks.com/enterprise-java/spring/tomcat-vs-jetty-vs-undertow-comparison-of-spring-boot-embedded-servlet-containers/

從測試結果看,這三個 Servlet 容器都具有不錯的性能,但 Undertow 性能更好,Tomcat 和 Jetty 緊隨其后。

Jetty 在啟動時的內存占用最大,為:311 MB, Tomcat 和 Undertow 的初始內存占用都很低,大約為:120 MB,而 Undertow 的初始內存占用最低,為:114 MB。

最后,關鍵的區別在於,Undertow 響應頭參數默認包含 HTTP 持久連接信息,這個頭參數在支持持久連接的客戶端時,可以通過重用連接來優化性能。

Show me the code

Undertow 目前有兩個主要版本:

  • 2.1:當前支持 Servlet 4.0, JDK8+ 的穩定版本;
  • 1.4:當前支持 Servlet 3.1, JDK7 的穩定版本;

獨立使用 Undertow 需要添加以下依賴:

<dependency>
    <groupId>io.undertow</groupId>
    <artifactId>undertow-core</artifactId>
    <version>2.1.0.Final</version>
</dependency>

<dependency>
    <groupId>io.undertow</groupId>
    <artifactId>undertow-servlet</artifactId>
    <version>2.1.0.Final</version>
</dependency>

<dependency>
    <groupId>io.undertow</groupId>
    <artifactId>undertow-websockets-jsr</artifactId>
    <version>2.1.0.Final</version>
</dependency>

以下示例來源官網:

public class HelloWorldServer {

    public static void main(final String[] args) {
        Undertow server = Undertow.builder()
                .addHttpListener(8080, "localhost")
                .setHandler(new HttpHandler() {
                    @Override
                    public void handleRequest(final HttpServerExchange exchange) throws Exception {
                        exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
                        exchange.getResponseSender().send("Hello World");
                    }
                }).build();
            server.start();
    }
}

這是一個使用了異常 IO 的簡單 Hello World 示例。

Spring Boot & Undertow

上面講到,Undertow 是為嵌入式而生的 Web 容器,又是 Spring Boot 默認集成的容器之一,下面棧長帶大家來看下如何在 Spring Boot 中使用 Undertow。

因為在 spring-boot-starter-web 啟動器中,Tomcat 是 Spring Boot 默認的嵌入式容器,即:spring-boot-starter-tomcat

Spring Boot 還提供了其他兩個啟動器以方便進行代替:

  • spring-boot-starter-jetty
  • spring-boot-starter-undertow

下面來簡單實戰下,如何在 Spring Boot 中使用 Undertow。Spring Boot 基礎知識就不介紹了,不熟悉的可以關注公眾號Java技術棧在后台回復boot獲取我寫的系列教程。

排除 Tomcat 依賴,然后加入 Undertow 依賴:

<dependencies>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <!-- Exclude the Tomcat dependency -->
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <!-- Use Undertow instead -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-undertow</artifactId>
    </dependency>

</dependencies>

一步就完成集成了,當然實際情況還需要在 application 配置文件中加入 Undertow 的更多自定義或者優化配置參數。

Undertow容器的具體配置可以看這兩個類:

  • org.springframework.boot.autoconfigure.web.ServerProperties
  • org.springframework.boot.autoconfigure.web.ServerProperties.Undertow

也可以看 Spring Boot 官方文檔:

https://docs.spring.io/spring-boot/docs/2.3.2.RELEASE/reference/htmlsingle/#server-properties

上面有所有 Server 配置參數和說明。

再寫一個測試方法測試下:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 微信公眾號:Java技術棧
 */
@RestController
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }

    @GetMapping(value = "/undertow/test")
    public String undertow() {
        return "hello undertow";
    }

}

啟動 Application:

如上所示,可以看到 Undertow 的啟動日志。

訪問測試方法:

http://localhost:8080/undertow/test

輸出成功,測試完成。

總結

本文對 Undertow 作了一個介紹和集成實戰,雖然 Undertow 性能很炸,但你可以去網上找一圈,根本沒啥學習資料。

所以,對於學習和一般應用來說,Tomcat 足矣,一方面 Tomcat 學習資料多,另一方面 Tomcat 用的更廣泛,很多坑別人幫你踩了,很多漏洞也已經暴露出來了。

那於那些一定要追求極致性能的又不想優化 Tomcat 的,可以考慮使用 Undertow,但同時你要有能力 Hold 住它,需要一定的積累經驗,不然出一個問題你線上卡半天顯然是不願意看到的。

最后,網上很多文章說干掉 Tomcat 而要使用 Undertow 的,這就有點誇張,我只能呵呵了,持有保留意見,用啥都行,關鍵能不能用好。

推薦去我的博客閱讀更多:

1.Java JVM、集合、多線程、新特性系列教程

2.Spring MVC、Spring Boot、Spring Cloud 系列教程

3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程

4.Java、后端、架構、阿里巴巴等大廠最新面試題

覺得不錯,別忘了點贊+轉發哦!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM