SpringBoot使用Undertow代替Tomcat
在SpringBoot框架中,我們使用最多的是Tomcat,這是SpringBoot預設的容器技術,而且是內嵌式的Tomcat。
同時,SpringBoot也支援Undertow容器,Undertow 是基於java nio的web伺服器,應用比較廣泛,內建提供的PathResourceManager,可以用來直接訪問檔案系統;如果你有檔案需要對外提供訪問,除了ftp,nginx等,undertow 也是一個不錯的選擇,作為java開發,服務搭建非常簡便。我們可以很方便的用Undertow替換Tomcat,而Undertow的效能和記憶體使用方面都優於Tomcat,那我們如何使用Undertow技術呢?
1. 配置Undertow
Spring boot內嵌容器預設為Tomcat,想要換成Undertow,非常容易,只需修改spring-boot-starter-web依賴,移除tomcat的依賴:
<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>
然後,新增undertow依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
這樣即可,使用預設引數啟動undertow伺服器。如果需要修改undertow引數,繼續往下看。
undertow的引數設定:
server:
port: 8084
http2:
enabled: true
undertow:
io-threads: 16
worker-threads: 256
buffer-size: 1024
buffers-per-region: 1024
direct-buffers: true
io-threads:IO執行緒數, 它主要執行非阻塞的任務,它們會負責多個連線,預設設定每個CPU核心一個執行緒,不可設定過大,否則啟動專案會報錯:開啟檔案數過多。
worker-threads:阻塞任務執行緒池,當執行類似servlet請求阻塞IO操作,undertow會從這個執行緒池中取得執行緒。它的值取決於系統執行緒執行任務的阻塞係數,預設值是 io-threads*8
以下配置會影響buffer,這些buffer會用於伺服器連線的IO操作,有點類似netty的池化記憶體管理。
buffer-size:每塊buffer的空間大小,越小的空間被利用越充分,不要設定太大,以免影響其他應用,合適即可
buffers-per-region:每個區分配的buffer數量,所以pool的大小是buffer-size * buffers-per-region
direct-buffers:是否分配的直接記憶體(NIO直接分配的堆外記憶體)
2. 啟動SpringBoot測試
Undertow啟動成功提示語:[INFO ] 2020-08-13 10:38:32 [main] o.s.b.w.e.u.UndertowServletWebServer - Undertow started on port(s) 80 (http) with context path ''
Tomcat啟動成功提示語: [INFO ] 2020-08-13 10:41:35 [main] o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 80 (http) with context path ''
3. Undertow的FileServer
import java.io.File; import io.undertow.Handlers; import io.undertow.Undertow; import io.undertow.server.handlers.resource.PathResourceManager; public class FileServer { public static void main(String[] args) { File file = new File("/"); Undertow server = Undertow.builder().addHttpListener(8080, "localhost") .setHandler(Handlers.resource(new PathResourceManager(file.toPath(), 100)) .setDirectoryListingEnabled(true)) .build(); server.start(); } }