Spring Boot中Tomcat、Jetty、Undertow哪个嵌入式服务器最好?
https://img-blog.csdnimg.cn/img_convert/b587c37962bd7c0e9f2928b1dfeda182.jpeg当我们使用 Spring Boot 创建一个 Web 应用步伐时,Apache Tomcat 是默认的嵌入式 Web 服务器。然而,我们也可以选择其他选项,如 Jetty 和 Undertow。但哪一个才是最佳选择呢?一起来探究一下!
为此,我们将构建一个名为 Greetings API 的简朴 Spring Boot 应用步伐。我们将在应用步伐的 pom.xml 中添加 Maven 配置文件,以便通过选择适当的配置文件在差别的嵌入式 Web 服务器之间切换。Tomcat 将是默认选项,但我们还将为 Jetty 和 Undertow 设置配置文件。
设置好配置文件后,我们将为每个 Web 服务器创建 Docker 镜像,并在单独的容器中运行它们。然后,我们将根据启动时间、CPU 和内存使用情况以及哀求处理惩罚性能对它们进行比较。
测试应用
Greetings API 是一个简朴的应用步伐,它公开了一个端点 /greetings?name=?,该端点返回一个问候语。如果没有提供name,它将返回“ World!”。否则,它将返回“ !”。
它的实现如下:
@Service
public class GreetingsService {
private static final String[] greetingWord = new String[]{"Hello", "Hi", "Olá", "Oi", "Hallo"};
public String randomGreetings(String name) {
try {
String word = greetingWord;
Thread.sleep(1000);
return "%s %s!".formatted(word, name);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
@RestController
@RequestMapping("/greetings")
public class GreetingsController {
private final GreetingsService greetingsService;
public GreetingsController(GreetingsService greetingsService) {
this.greetingsService = greetingsService;
}
@GetMapping
public String greeting(@RequestParam(required = false, defaultValue = "World") String name) {
return greetingsService.randomGreetings(name);
}
}
@Service
public class GreetingsService {
private static final String[] greetingWord = new String[]{"Hello", "Hi", "Olá", "Oi", "Hallo"};
public String randomGreetings(String name) {
try {
String word = greetingWord;
Thread.sleep(1000);
return "%s %s!".formatted(word, name);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
@RestController
@RequestMapping("/greetings")
public class GreetingsController {
private final GreetingsService greetingsService;
public GreetingsController(GreetingsService greetingsService) {
this.greetingsService = greetingsService;
}
@GetMapping
public String greeting(@RequestParam(required = false, defaultValue = "World") String name) {
return greetingsService.randomGreetings(name);
}
}
@Service
public class GreetingsService {
private static final String[] greetingWord = new String[]{"Hello", "Hi", "Olá", "Oi", "Hallo"};
public String randomGreetings(String name) {
try {
String word = greetingWord;
Thread.sleep(1000);
return "%s %s!".formatted(word, name);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
@RestController
@RequestMapping("/greetings")
public class GreetingsController {
private final GreetingsService greetingsService;
public GreetingsController(GreetingsService greetingsService) {
this.greetingsService = greetingsService;
}
@GetMapping
public String greeting(@RequestParam(required = false, defaultValue = "World") String name) {
return greetingsService.randomGreetings(name);
}
}Jetty和Undertow的配置
在pom.xml中增加Jetty和Undertow的配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
...
<dependencies>
...
</dependencies>
<profiles>
<!-- Jetty Profile -->
<profile>
<id>jetty</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<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 Jetty instead -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>
</profile>
<!-- Undertow Profile -->
<profile>
<id>undertow</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<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>
</profile>
</profiles>
<build>
...
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
...
<dependencies>
...
</dependencies>
<profiles>
<!-- Jetty Profile -->
<profile>
<id>jetty</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<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 Jetty instead -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>
</profile>
<!-- Undertow Profile -->
<profile>
<id>undertow</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<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>
</profile>
</profiles>
<build>
...
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
...
<dependencies>
...
</dependencies>
<profiles>
<!-- Jetty Profile -->
<profile>
<id>jetty</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<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 Jetty instead -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>
</profile>
<!-- Undertow Profile -->
<profile>
<id>undertow</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<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>
</profile>
</profiles>
<build>
...
</build>
</project>application.properties 配置
分别配置Tomcat、Jetty和Undertow线程配置,具体如下:
# Maximum amount of worker threads. 200 is the default.
server.tomcat.threads.max=200
# Maximum number of threads. 200 is the default.
server.jetty.threads.max=200
# Number of worker threads. The default is 8 times the number of I/O threads.
# The number of I/O threads is set by the property "server.undertow.threads.io" whose default is derived from the number of available processors.
server.undertow.threads.worker=200
# Maximum amount of worker threads. 200 is the default.
server.tomcat.threads.max=200
# Maximum number of threads. 200 is the default.
server.jetty.threads.max=200
# Number of worker threads. The default is 8 times the number of I/O threads.
# The number of I/O threads is set by the property "server.undertow.threads.io" whose default is derived from the number of available processors.
server.undertow.threads.worker=200
# Maximum amount of worker threads. 200 is the default.
server.tomcat.threads.max=200
# Maximum number of threads. 200 is the default.
server.jetty.threads.max=200
# Number of worker threads. The default is 8 times the number of I/O threads.
# The number of I/O threads is set by the property "server.undertow.threads.io" whose default is derived from the number of available processors.
server.undertow.threads.worker=200这里我们将所有Web服务器的最大线程数设置为200
我们创建了一个高质量的技术交换群,与良好的人在一起,本身也会良好起来,赶紧点击加群,享受一起发展的快乐。
更多关于Spring的技术学习,可关注 https://spring4all.com,专注讨论关于Spring的一切。
构建Docker镜像
上面我们已经为 Jetty 和 Undertow 配置了 Maven 配置文件,所以我们可以为每个嵌入式 Web 服务器构建 Docker 镜像。
# 构建Tomcat的镜像
./mvnw clean -DskipTests spring-boot:build-image\
-Dspring-boot.build-image.imageName=greetings-api-tomcat:latest
# 构建Jetty的镜像
./mvnw clean -DskipTests spring-boot:build-image -Pjetty \
-Dspring-boot.build-image.imageName=greetings-api-jetty:latest
# 构建Undertow的镜像
./mvnw clean -DskipTests spring-boot:build-image -Pundertow \
-Dspring-boot.build-image.imageName=greetings-api-undertow:latest
# 构建Tomcat的镜像
./mvnw clean -DskipTests spring-boot:build-image\
-Dspring-boot.build-image.imageName=greetings-api-tomcat:latest
# 构建Jetty的镜像
./mvnw clean -DskipTests spring-boot:build-image -Pjetty \
-Dspring-boot.build-image.imageName=greetings-api-jetty:latest
# 构建Undertow的镜像
./mvnw clean -DskipTests spring-boot:build-image -Pundertow \
-Dspring-boot.build-image.imageName=greetings-api-undertow:latest
# 构建Tomcat的镜像
./mvnw clean -DskipTests spring-boot:build-image\
-Dspring-boot.build-image.imageName=greetings-api-tomcat:latest
# 构建Jetty的镜像
./mvnw clean -DskipTests spring-boot:build-image -Pjetty \
-Dspring-boot.build-image.imageName=greetings-api-jetty:latest
# 构建Undertow的镜像
./mvnw clean -DskipTests spring-boot:build-image -Pundertow \
-Dspring-boot.build-image.imageName=greetings-api-undertow:latest基准测试
为了从我们的 Docker 容器中收集基准测试的紧张数据,我们将使用这个开源项目:https://github.com/ivangfr/api-oha-benchmarker ,
基准测试将包罗对每个嵌入式 Web 服务器的 Docker 容器进行负载测试。每次迭代,我们将进行如下操作:
[*]启动 Docker 容器
[*]使用 100、300、900 和最终 2700 个并发哀求进行 OHA 测试
[*]关闭 Docker 容器。
下面,我们在使用 OHA 对 Docker 容器进行 100、300、900 和最终 2700 个并发哀求的负载测试后,获得的结果数据:
Application | numRequests | Concurrency | Success rate(%) | Total(secs) | Slowest(secs) | Fastest(secs) | Average(secs) | Requests/sec |
---------------------- + ----------- + ----------- + --------------- + ----------- + ------------- + ------------- + ------------- + ------------ |
greetings-api-tomcat | 100 | 100 | 100.00 | 1.2949 | 1.2942 | 1.2701 | 1.2822 | 77.2256 |
greetings-api-tomcat | 300 | 300 | 100.00 | 2.1069 | 2.0835 | 1.0311 | 1.4158 | 142.3913 |
greetings-api-tomcat | 900 | 900 | 100.00 | 5.1386 | 5.0797 | 1.0283 | 2.8856 | 175.1446 |
greetings-api-tomcat | 2700 | 2700 | 100.00 | 14.3752 | 14.2423 | 1.0296 | 7.4867 | 187.8241 |
...................... + ........... + ........... + ............... + ........... + ............. + ............. + ............. + ............ |
greetings-api-jetty | 100 | 100 | 100.00 | 2.0717 | 2.0708 | 1.2639 | 1.5895 | 48.2692 |
greetings-api-jetty | 300 | 300 | 100.00 | 3.1081 | 3.1056 | 1.0307 | 1.7496 | 96.5223 |
greetings-api-jetty | 900 | 900 | 100.00 | 5.1943 | 5.1762 | 1.0381 | 3.0216 | 173.2659 |
greetings-api-jetty | 2700 | 2700 | 100.00 | 15.3022 | 15.2278 | 1.0160 | 7.9127 | 176.4455 |
...................... + ........... + ........... + ............... + ........... + ............. + ............. + ............. + ............ |
greetings-api-undertow | 100 | 100 | 100.00 | 1.3076 | 1.3066 | 1.2665 | 1.2833 | 76.4765 |
greetings-api-undertow | 300 | 300 | 100.00 | 2.0819 | 2.0776 | 1.0413 | 1.4058 | 144.0982 |
greetings-api-undertow | 900 | 900 | 100.00 | 5.1443 | 5.1121 | 1.0780 | 2.8783 | 174.9493 |
greetings-api-undertow | 2700 | 2700 | 100.00 | 14.1748 | 14.0861 | 1.0758 | 7.3721 | 190.4783 |
Application | numRequests | Concurrency | Success rate(%) | Total(secs) | Slowest(secs) | Fastest(secs) | Average(secs) | Requests/sec |
---------------------- + ----------- + ----------- + --------------- + ----------- + ------------- + ------------- + ------------- + ------------ |
greetings-api-tomcat | 100 | 100 | 100.00 | 1.2949 | 1.2942 | 1.2701 | 1.2822 | 77.2256 |
greetings-api-tomcat | 300 | 300 | 100.00 | 2.1069 | 2.0835 | 1.0311 | 1.4158 | 142.3913 |
greetings-api-tomcat | 900 | 900 | 100.00 | 5.1386 | 5.0797 | 1.0283 | 2.8856 | 175.1446 |
greetings-api-tomcat | 2700 | 2700 | 100.00 | 14.3752 | 14.2423 | 1.0296 | 7.4867 | 187.8241 |
...................... + ........... + ........... + ............... + ........... + ............. + ............. + ............. + ............ |
greetings-api-jetty | 100 | 100 | 100.00 | 2.0717 | 2.0708 | 1.2639 | 1.5895 | 48.2692 |
greetings-api-jetty | 300 | 300 | 100.00 | 3.1081 | 3.1056 | 1.0307 | 1.7496 | 96.5223 |
greetings-api-jetty | 900 | 900 | 100.00 | 5.1943 | 5.1762 | 1.0381 | 3.0216 | 173.2659 |
greetings-api-jetty | 2700 | 2700 | 100.00 | 15.3022 | 15.2278 | 1.0160 | 7.9127 | 176.4455 |
...................... + ........... + ........... + ............... + ........... + ............. + ............. + ............. + ............ |
greetings-api-undertow | 100 | 100 | 100.00 | 1.3076 | 1.3066 | 1.2665 | 1.2833 | 76.4765 |
greetings-api-undertow | 300 | 300 | 100.00 | 2.0819 | 2.0776 | 1.0413 | 1.4058 | 144.0982 |
greetings-api-undertow | 900 | 900 | 100.00 | 5.1443 | 5.1121 | 1.0780 | 2.8783 | 174.9493 |
greetings-api-undertow | 2700 | 2700 | 100.00 | 14.1748 | 14.0861 | 1.0758 | 7.3721 | 190.4783 |
Application | numRequests | Concurrency | Success rate(%) | Total(secs) | Slowest(secs) | Fastest(secs) | Average(secs) | Requests/sec |
---------------------- + ----------- + ----------- + --------------- + ----------- + ------------- + ------------- + ------------- + ------------ |
greetings-api-tomcat | 100 | 100 | 100.00 | 1.2949 | 1.2942 | 1.2701 | 1.2822 | 77.2256 |
greetings-api-tomcat | 300 | 300 | 100.00 | 2.1069 | 2.0835 | 1.0311 | 1.4158 | 142.3913 |
greetings-api-tomcat | 900 | 900 | 100.00 | 5.1386 | 5.0797 | 1.0283 | 2.8856 | 175.1446 |
greetings-api-tomcat | 2700 | 2700 | 100.00 | 14.3752 | 14.2423 | 1.0296 | 7.4867 | 187.8241 |
...................... + ........... + ........... + ............... + ........... + ............. + ............. + ............. + ............ |
greetings-api-jetty | 100 | 100 | 100.00 | 2.0717 | 2.0708 | 1.2639 | 1.5895 | 48.2692 |
greetings-api-jetty | 300 | 300 | 100.00 | 3.1081 | 3.1056 | 1.0307 | 1.7496 | 96.5223 |
greetings-api-jetty | 900 | 900 | 100.00 | 5.1943 | 5.1762 | 1.0381 | 3.0216 | 173.2659 |
greetings-api-jetty | 2700 | 2700 | 100.00 | 15.3022 | 15.2278 | 1.0160 | 7.9127 | 176.4455 |
...................... + ........... + ........... + ............... + ........... + ............. + ............. + ............. + ............ |
greetings-api-undertow | 100 | 100 | 100.00 | 1.3076 | 1.3066 | 1.2665 | 1.2833 | 76.4765 |
greetings-api-undertow | 300 | 300 | 100.00 | 2.0819 | 2.0776 | 1.0413 | 1.4058 | 144.0982 |
greetings-api-undertow | 900 | 900 | 100.00 | 5.1443 | 5.1121 | 1.0780 | 2.8783 | 174.9493 |
greetings-api-undertow | 2700 | 2700 | 100.00 | 14.1748 | 14.0861 | 1.0758 | 7.3721 | 190.4783 |下图显示了启动时间以及最大 CPU 和内存消耗:
Application | StartUpTime(sec) | Max CPU(%) | Max Memory(MB) |
---------------------- + ---------------- + ---------- + -------------- |
greetings-api-tomcat | 1.8920 | 101.26 | 269.10 |
greetings-api-jetty | 1.9790 | 100.40 | 217.70 |
greetings-api-undertow | 2.0450 | 124.15 | 237.50 |
Application | StartUpTime(sec) | Max CPU(%) | Max Memory(MB) |
---------------------- + ---------------- + ---------- + -------------- |
greetings-api-tomcat | 1.8920 | 101.26 | 269.10 |
greetings-api-jetty | 1.9790 | 100.40 | 217.70 |
greetings-api-undertow | 2.0450 | 124.15 | 237.50 |
Application | StartUpTime(sec) | Max CPU(%) | Max Memory(MB) |
---------------------- + ---------------- + ---------- + -------------- |
greetings-api-tomcat | 1.8920 | 101.26 | 269.10 |
greetings-api-jetty | 1.9790 | 100.40 | 217.70 |
greetings-api-undertow | 2.0450 | 124.15 | 237.50 |响应时间
https://img-blog.csdnimg.cn/img_convert/9954cfbaec70982012d9fe8f24b2ca74.png
我们可以看到,在处理惩罚 100 个并发哀求时,使用 Tomcat 的应用步伐最快,时间为 1.2949 秒,紧随厥后的是使用 Undertow 的应用步伐,时间为 1.3076 秒。使用 Jetty 的应用步伐最慢,时间为 2.0717 秒。
在处理惩罚 300 个并发哀求时,使用 Undertow 的应用步伐略快,时间为 2.0819 秒,紧随厥后的是使用 Tomcat 的应用步伐,时间为 2.1069 秒。使用 Jetty 的应用步伐最慢,时间为 3.1081 秒。
对于 900 个并发哀求,使用 Tomcat 的应用步伐略快,时间为 5.1386 秒,紧随厥后的是使用 Undertow 的应用步伐,时间为 5.1443 秒,以及使用 Jetty 的应用步伐,时间为 5.1943 秒。
最后,在处理惩罚 2700 个并发哀求时,使用 Undertow 的应用步伐最快,时间为 14.1748 秒,紧随厥后的是使用 Tomcat 的应用步伐,时间为 14.3752 秒。使用 Jetty 的应用步伐最慢,时间为 15.3022 秒。
启动时间
https://img-blog.csdnimg.cn/img_convert/f0dbb9590c4222742ee343abf0b440ac.png
可以看到,使用 Tomcat 的应用步伐启动时间最快,为 1.8920 秒,紧随厥后的是使用 Jetty 的应用步伐,时间为 1.9790 秒。启动最慢的是使用 Undertow 的应用步伐,耗时 2.0450 秒。
内存占用
https://img-blog.csdnimg.cn/img_convert/81ede1a6e95ee4e84a4b42a62fe9b64c.png
可以看到,使用 Jetty 的应用步伐最大内存消耗最低,为 217.70 MB,紧随厥后的是使用 Undertow 的应用步伐,为 237.50 MB。最大内存消耗最高的是使用 Tomcat 的应用步伐,为 269.10 MB。
CPU占用
https://img-blog.csdnimg.cn/img_convert/8202dfbd41f6752eb1fefb76d6bf13a0.png
以看到,使用 Jetty 的应用步伐最大 CPU 使用率最低,为 100.40%,紧随厥后的是使用 Tomcat 的应用步伐,为 101.26%。最高 CPU 使用率的是使用 Undertow 的应用步伐,为 124.15%。
结论
根据上面的测试,可以看到Tomcat、Jetty 和 Undertow 各有优势。使用 Tomcat 的应用步伐启动速率最快,而且能够很好地处理惩罚差别级别的流量,尽管它使用更多的内存。使用 Undertow 的应用步伐在处理惩罚大量流量时表现最佳,但它的 CPU 使用率更高,启动时间稍长。使用 Jetty 的应用步伐在响应流量方面较慢,但它使用的内存和 CPU 更少,如果你希望节省资源,这是一个不错的选择。
选择最佳的 Web 服务器取决于你的需求。如果你的应用步伐将处理惩罚大量流量,Undertow 可能是最佳选择。如果你想要一个全能的选择,Tomcat 是一个可靠的选择。而如果节省内存和 CPU 是最紧张的,Jetty 是一个不错的选择。
最后,留言区说说你现在用的哪个呢?
来源:https://spring4all.com/forum-post/7674.html
我们创建了一个高质量的技术交换群,与良好的人在一起,本身也会良好起来,赶紧点击加群,享受一起发展的快乐。
你还在购买国内的各种昂贵又低质的技术教程吗?这里给大家推荐下我们自研的Youtube视频语音转换插件(https://youtube-dubbing.com/),一键外语转中文,英语不好的小伙伴也可以轻松的学习油管上的优质教程了,下面是演示视频,可以直观的感受一下:
如果您觉得这款插件不错,也可以推荐给您身边的朋友,现在我们开通了分享赚钱功能,只要安装本插件登录注册之后,获取约请链接,放到你的博客侧边栏、友谊链接大概发到朋友圈、微博、X等交际平台,就能获得积分,积分现在是可以i直接提现的哦~
推荐阅读
[*]如安在 Spring Boot 中创建自界说注解简化重复编码
[*]Spring AI 更新:支持OpenAI的布局化输出,增强对JSON响应的支持
[*]IntelliJ IDEA 2024.2 发布:Spring Data JPA即时查询、主动补全cron表达式
[*]Spring Boot 中使用 JSON Schema 来校验复杂JSON数据
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]