Spring Boot中Tomcat、Jetty、Undertow哪个嵌入式服务器最好?
创始人
2024-09-26 14:50:04
0

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,它将返回“[greeting-word] World!”。否则,它将返回“[greeting-word] [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[ThreadLocalRandom.current().nextInt(greetingWord.length)];             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[ThreadLocalRandom.current().nextInt(greetingWord.length)];             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[ThreadLocalRandom.current().nextInt(greetingWord.length)];             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的配置

      ...              ...                                         jetty                              false                                                                org.springframework.boot                     spring-boot-starter-web                                                                                                    org.springframework.boot                             spring-boot-starter-tomcat                                                                                                                      org.springframework.boot                     spring-boot-starter-jetty                                                                      undertow                              false                                                                org.springframework.boot                     spring-boot-starter-web                                                                                                    org.springframework.boot                             spring-boot-starter-tomcat                                                                                                                      org.springframework.boot                     spring-boot-starter-undertow                                                          ...             ...              ...                                           jetty                              false                                                                org.springframework.boot                     spring-boot-starter-web                                                                                                    org.springframework.boot                             spring-boot-starter-tomcat                                                                                                                      org.springframework.boot                     spring-boot-starter-jetty                                                                       undertow                              false                                                                org.springframework.boot                     spring-boot-starter-web                                                                                                    org.springframework.boot                             spring-boot-starter-tomcat                                                                                                                      org.springframework.boot                     spring-boot-starter-undertow                                                            ...              ...              ...                                           jetty                              false                                                                org.springframework.boot                     spring-boot-starter-web                                                                                                    org.springframework.boot                             spring-boot-starter-tomcat                                                                                                                      org.springframework.boot                     spring-boot-starter-jetty                                                                       undertow                              false                                                                org.springframework.boot                     spring-boot-starter-web                                                                                                    org.springframework.boot                             spring-boot-starter-tomcat                                                                                                                      org.springframework.boot                     spring-boot-starter-undertow                                                            ...       

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 容器进行负载测试。每次迭代,我们将进行如下操作:

  1. 启动 Docker 容器

  2. 使用 100、300、900 和最终 2700 个并发请求进行 OHA 测试

  3. 关闭 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 |

响应时间

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 秒。

启动时间

f0dbb9590c4222742ee343abf0b440ac.png

可以看到,使用 Tomcat 的应用程序启动时间最快,为 1.8920 秒,紧随其后的是使用 Jetty 的应用程序,时间为 1.9790 秒。启动最慢的是使用 Undertow 的应用程序,耗时 2.0450 秒。

内存占用

81ede1a6e95ee4e84a4b42a62fe9b64c.png

可以看到,使用 Jetty 的应用程序最大内存消耗最低,为 217.70 MB,紧随其后的是使用 Undertow 的应用程序,为 237.50 MB。最大内存消耗最高的是使用 Tomcat 的应用程序,为 269.10 MB。

CPU占用

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数据

相关内容

热门资讯

安卓系统如何调出亮度,安卓系统... 手机屏幕亮度不够,看不清内容,是不是有点头疼呢?别急,今天就来教你怎么轻松调出安卓系统的亮度,让你的...
安卓子系统无法安装,安卓子系统... 最近是不是你也遇到了安卓子系统无法安装的烦恼?别急,让我来给你详细解析一下这个问题,让你轻松解决它!...
如何装谷歌 安卓系统,一键解锁... 你有没有想过,让你的安卓手机瞬间变身成为谷歌的忠实粉丝呢?想象那些只属于谷歌的独家应用和功能,是不是...
安卓能用斑马系统吗,探索跨界融... 你有没有想过,你的安卓手机能不能用斑马系统呢?这可是个让人好奇的问题,毕竟斑马系统在智能汽车领域可是...
originosocean切换... 你知道吗?最近有个大新闻在科技圈里炸开了锅,那就是OriginOS系统要切换回安卓系统了!这可真是让...
安卓系统后期卡顿,揭秘原因与优... 手机用久了是不是感觉越来越慢,打开个应用都要等半天?这不,最近好多朋友都跟我抱怨说,他们的安卓手机怎...
魅蓝系统是不是安卓系统,深度解... 你有没有听说过魅蓝系统?是不是好奇它是不是安卓系统呢?别急,今天就来给你揭秘这个谜团,让你对魅蓝系统...
安卓系统与ios系统差距在哪,... 你有没有发现,现在手机市场上安卓系统和iOS系统就像是一对“欢喜冤家”,各有各的拥趸,各有各的特色。...
安卓手机清理系统文件,安卓手机... 亲爱的手机控们,你是不是也和我一样,每天对着手机屏幕,却总觉得内存不够用呢?别急,今天就来和你聊聊如...
安卓系统滚动条,功能与设计解析 你有没有发现,在使用安卓手机的时候,有时候屏幕下方会出现一条细细的滚动条呢?这可不是什么小问题,它可...
安卓权限系统的含义,保障安全与... 你知道吗?在智能手机的世界里,有一个超级重要的东西叫做“安卓权限系统”。它就像是一个超级管家,负责管...
华为平板安卓系统9,畅享智能新... 亲爱的读者们,你是否曾想过,一款平板电脑,如何能让你在工作和娱乐中游刃有余?今天,就让我带你走进华为...
鸿蒙系统与安卓关系,探索与安卓... 你知道吗?最近科技圈里有个大新闻,那就是鸿蒙系统与安卓的关系。这俩家伙,一个是华为的亲儿子,一个是全...
最好安卓系统手机排名,性能与创... 你有没有想过,在这个科技飞速发展的时代,拥有一部性能卓越的安卓手机是多么重要的事情呢?想象每天陪伴你...
小米电视 进入安卓系统,畅享安... 亲爱的读者们,你是否也和我一样,对科技产品的新鲜事充满好奇?今天,我要和你聊聊一个让人眼前一亮的话题...
怎么用安卓系统下载,轻松掌握下... 你有没有想过,手机里装了安卓系统,怎么才能轻松下载那些好玩的应用或者实用的工具呢?别急,今天就来给你...
降低安卓系统内存占用,安卓系统... 手机内存不够用,是不是你也遇到了这样的烦恼?别急,今天就来给你支几招,让你的安卓手机内存占用大大降低...
索尼 安卓升级系统版本,畅享智... 你有没有发现,你的索尼手机最近是不是有点儿“闹腾”?没错,它又来给你升级系统版本了!这回,索尼可是下...
如何导入安卓系统版本,轻松掌握... 你有没有想过,你的安卓手机系统是不是该升级一下了呢?别看它现在运行得还挺顺畅的,但谁知道呢,可能某个...
汽车导航安装安卓系统,汽车智能... 你有没有想过,你的汽车导航系统是不是也该来个“大变身”了呢?想象当你开着车,一边听着音乐,一边用手机...