赞
踩
这里记录一下:
我这边测试发现,spring boot 2.1.6的Tomcat和undertow性能没多大差异,可能业务层的调用导致了测试的结果。具体性能要更具实际业务来对比,这样才能提高业务的处理能力。
每个SpringBootWeb应用程序都包含一个嵌入式Web服务器。此功能导致了许多操作方法问题,包括如何更改嵌入式服务器以及如何配置嵌入式服务器。本节回答这些问题。
许多Springboot程序都包含默认的嵌入式容器。
对于servlet堆栈应用程序,spring-boot-starter-web
通过包含spring-boot-starter-tomcat
来包含Tomcat,但是您也可以使用spring-boot-starter-jetty
或 spring-boot-starter-undertow
来代替。
对于响应式应用程序,spring-boot-starter-webflux
通过包含spring-boot-starter-reactor-netty
来引用响应式 netty(netty比较适合),但是您也可以使用spring-boot-starter-tomcat
, spring-boot-starter-jetty
, 或spring-boot-starter-undertow
来代替。
下面的Maven示例演示了如何排除Tomcat并包括SpringMVC的Jetty:
- <properties>
- <servlet-api.version>3.1.0</servlet-api.version>
- </properties>
- <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>

Servlet API的版本已被重写,与Tomcat9和Undertow2.0不同,Jetty9.4不支持Servlet 4.0。
下面的Gradle示例演示了如何排除netty,并包括SpringWebFlux的Untow:
下面几个网上的测试内容:
https://www.chainnews.com/articles/359576081501.htm#
https://www.jianshu.com/p/f7cb40a8ce22
https://www.cnblogs.com/duanxz/p/9337022.html
https://zhuanlan.zhihu.com/p/54086085
################################################################
下面文章转自:https://my.oschina.net/shyloveliyi/blog/2980868
昨天发了一个《SpringBoot服务器压测对比(jetty、tomcat、undertow)》,本是工作的一个笔记,没想到被红薯翻牌了(荣幸之至)。看了OSCer的回复,感觉需要重新梳理下,因为确实存在描述不清和不合理的配置。
这篇博客的目的,不是复述上一篇博客,而是尽量规范的去做一次压测对比,并且能够清晰的描述出过程和结果。
为了保证尽量少的干扰,这里不再在虚拟机上运行服务,而是直接在物理机上运行服务,并且在这台物理机上安装ab工具。
服务器配置是2个CPU,单个CPU8核,总共内存40G,1T的RAID5机械硬盘。服务器安装的系统是Centos7.5,系统优化同《Centos7高并发优化》所述。但额外的,因工作需要,这台物理机上有6个虚机,是不能关闭的。以下是简单的top展示:
感谢@TGVvbmFyZA 的建议,测试项目不再使用生产项目,而是从Springboot官网打包2.x版本的项目,这样的目的是减少生产项目中不必要的依赖,从而避免不必要的开销。以下是简单的项目介绍:
序号 | 名称 | 版本 |
1 | springboot | 2.1.1 |
2 | java | 1.8 |
我已将项目放到Gitee,地址:https://gitee.com/loveliyiyi/test4server
以下贴出关键代码,以便更好理解。
- package com.shy.test4server;
-
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.context.request.async.WebAsyncTask;
-
- /**
- * @ClassName: TestController
- * @Description: TODO(这里用一句话描述这个类的作用)
- * @author chengcai.shang@cmgplex.com
- * @date 2018年12月7日 上午9:36:25
- *
- */
- @Controller
- @RequestMapping("/test")
- public class TestController {
- /**
- * 未使用HTTP异步的接口
- *
- * @Title: testCeilingNoAsync
- * @Description: TODO(这里用一句话描述这个方法的作用)
- * @date 2018年12月7日 上午9:40:57
- */
- @GetMapping("/testCeilingNoAsync")
- public String testCeilingNoAsync() {
- return "";
- }
-
- /**
- * 使用HTTP异步的接口
- *
- * @Title: testCeilingNoAsync
- * @Description: TODO(这里用一句话描述这个方法的作用)
- * @date 2018年12月7日 上午9:40:57
- */
- @GetMapping("/testCeilingWithAsync")
- public WebAsyncTask<String> testCeilingWithAsync() {
- return new WebAsyncTask(() -> {
- return "";
- });
- }
- }

不同的服务器容器优化参数均不一致,以下是本次测试主要优化的地方:
序号 | 服务容器 | 优化参数 |
1 | tomcat | 最大连接数server.tomcat.max-threads=400 |
2 | jetty | 最大连接数(400)和最小连接数(10) |
3 | undertow | cpu核数(16)和工作线程数(400) |
4 | http异步 | 线程池core=10,max=400,queue=200 |
以下优化步骤:
针对tomcat,在application.properties中加入server.tomcat.max-threads=400即可。
针对jetty,在config目录加入JettyConfig类
- package com.shy.test4server.config;
-
- import org.apache.catalina.Server;
- import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
-
- /**
- * @ClassName: JettyConfig
- * @Description: TODO(这里用一句话描述这个类的作用)
- * @date 2018年12月7日 上午9:53:46
- *
- */
- @Configuration
- public class JettyConfig {
- @Bean
- public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory(
- JettyServerCustomizer jettyServerCustomizer) {
- JettyEmbeddedServletContainerFactory factory = new JettyEmbeddedServletContainerFactory();
- factory.addServerCustomizers(jettyServerCustomizer);
- return factory;
- }
-
- @Bean
- public JettyServerCustomizer jettyServerCustomizer() {
- return server -> {
- threadPool(server);
- };
- }
-
- private void threadPool(Server server) {
- // Tweak the connection config used by Jetty to handle incoming HTTP
- // connections
- final QueuedThreadPool threadPool = server.getBean(QueuedThreadPool.class);
- // 默认最大线程连接数200
- threadPool.setMaxThreads(100);
- // 默认最小线程连接数8
- threadPool.setMinThreads(20);
- // 默认线程最大空闲时间60000ms
- threadPool.setIdleTimeout(60000);
- }
- }

针对undertow,在application.properties中加入server.undertow.io-threads=16和server.undertow.worker-threads=400即可
针对http异步,优化代码如下:
- package com.shy.test4server.config;
-
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
- import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
-
- /**
- * @ClassName: SpringmvcConfig
- * @Description: TODO(这里用一句话描述这个类的作用)
- * @date 2018年12月7日 上午9:59:06
- *
- */
- @Configuration
- public class SpringmvcConfig {
- @Bean
- public void configThreadPoll(AsyncSupportConfigurer asyncSupportConfigurer) {
- ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
- threadPool.setCorePoolSize(10);
- threadPool.setMaxPoolSize(400);
- threadPool.setQueueCapacity(200);
- threadPool.initialize();
- asyncSupportConfigurer.setTaskExecutor(threadPool);
- }
- }

另,所有测试中,日志均关闭。
由于三个服务器的优化参数不一致,没法做统一配置,然后观察结果。故只能不断调整参数获取最大的结果,然后比对最终结果,虽然这样得出结果有点片面,但目前也只能这么干。另外,不再辅以Jprofiler监控,因为Jprofiler会影响一定得性能。以下是压测步骤:
1、使用tomcat,压测两个接口,按不同并发访问10000次,然后不断调整参数,获取最大结果。由此可得出纯tomcat和tomcat+http异步的结果。
2、使用jetty,压测两个接口,按不同并发访问10000次,然后不断调整参数,获取最大结果。由此可得出纯jetty和jetty+http异步的结果。
3、使用udertow,压测两个接口,按不同并发访问10000次,然后不断调整参数,获取最大结果。由此可得出纯udertow和udertow+http异步的结果。
启动命令
java -server -Dserver.tomcat.max-threads=400 -Dspringmvc.thread.core=10 -Dspringmvc.thread.max=400 -Dspringmvc.thread.queue=200 -Xms512m -Xmx512m -jar test4server.jar
压测命令
- ab -n 10000 -c 50 http://localhost:8080/test/testCeilingNoAsync
- ab -n 10000 -c 100 http://localhost:8080/test/testCeilingNoAsync
- ab -n 10000 -c 200 http://localhost:8080/test/testCeilingNoAsync
- ab -n 10000 -c 50 http://localhost:8080/test/testCeilingWithAsync
- ab -n 10000 -c 100 http://localhost:8080/test/testCeilingWithAsync
- ab -n 10000 -c 200 http://localhost:8080/test/testCeilingWithAsync
压测结果:
启动命令
java -server -Djetty.thread.max=400 -Djetty.thread.min=10 -Dspringmvc.thread.core=10 -Dspringmvc.thread.max=400 -Dspringmvc.thread.queue=200 -Xms512m -Xmx512m -jar test4server.jar
压测命令
- ab -n 10000 -c 50 http://localhost:8080/test/testCeilingNoAsync
- ab -n 10000 -c 100 http://localhost:8080/test/testCeilingNoAsync
- ab -n 10000 -c 200 http://localhost:8080/test/testCeilingNoAsync
- ab -n 10000 -c 50 http://localhost:8080/test/testCeilingWithAsync
- ab -n 10000 -c 100 http://localhost:8080/test/testCeilingWithAsync
- ab -n 10000 -c 200 http://localhost:8080/test/testCeilingWithAsync
压测结果:
启动命令
java -server -Dserver.undertow.io-threads=16 -Dserver.undertow.worker-threads=400 -Dspringmvc.thread.core=10 -Dspringmvc.thread.max=400 -Dspringmvc.thread.queue=200 -Xms512m -Xmx512m -jar test4server.jar
压测命令
- ab -n 10000 -c 50 http://localhost:8080/test/testCeilingNoAsync
- ab -n 10000 -c 100 http://localhost:8080/test/testCeilingNoAsync
- ab -n 10000 -c 200 http://localhost:8080/test/testCeilingNoAsync
- ab -n 10000 -c 50 http://localhost:8080/test/testCeilingWithAsync
- ab -n 10000 -c 100 http://localhost:8080/test/testCeilingWithAsync
- ab -n 10000 -c 200 http://localhost:8080/test/testCeilingWithAsync
压测结果:
HTTP异步的目的在帮助dispatcherservlet分担压力,提升吞吐量。但如果运行在NIO模式的服务容器上,就会产生负面影响,因为NIO本身就做了类似的事情,此时再加HTTP异步,则相当于又加了N多不必要的线程,导致性能主要消耗在线程的开销上,所以建议使用tomcat作为内嵌容器并且没有开启tomcat的NIO模式时,可以配合HTTP异步来提升程序性能。尤其是当业务繁重时,提升效果尤其明显。
在基于天花板接口的测试中,综合对比tomcat、jetty、undertow,可以发现undertow相对性能更高点。但此结果并不一定准确,因为测试方案里只进行了很简单的参数调整,以及并没有针对实际业务代码进行测试。不过源码我已提供,有兴趣的可以实际测试下。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。