后续之《SpringBoot服务器压测对比(jetty、tomcat、undertow)》
一、前言
昨天发了一个《SpringBoot服务器压测对比(jetty、tomcat、undertow)》,本是工作的一个笔记,没想到被红薯翻牌了(荣幸之至)。看了OSCer的回复,感觉需要重新梳理下,因为确实存在描述不清和不合理的配置。
这篇博客的目的,不是复述上一篇博客,而是尽量规范的去做一次压测对比,并且能够清晰的描述出过程和结果。
二、准备
1、服务器
为了保证尽量少的干扰,这里不再在虚拟机上运行服务,而是直接在物理机上运行服务,并且在这台物理机上安装ab工具。
服务器配置是2个CPU,单个CPU8核,总共内存40G,1T的RAID5机械硬盘。服务器安装的系统是Centos7.5,系统优化同《Centos7高并发优化》所述。但额外的,因工作需要,这台物理机上有6个虚机,是不能关闭的。以下是简单的top展示:
2、测试项目
感谢@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 "";
});
}
}
3、项目优化
不同的服务器容器优化参数均不一致,以下是本次测试主要优化的地方:
序号 | 服务容器 | 优化参数 |
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异步的结果。
四、压测过程
1、tomcat
启动命令
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
压测结果:
2、jetty
启动命令
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
压测结果:
3、undertow
启动命令
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
压测结果:
五、压测结果
1、关于HTTP异步
HTTP异步的目的在帮助dispatcherservlet分担压力,提升吞吐量。但如果运行在NIO模式的服务容器上,就会产生负面影响,因为NIO本身就做了类似的事情,此时再加HTTP异步,则相当于又加了N多不必要的线程,导致性能主要消耗在线程的开销上,所以建议使用tomcat作为内嵌容器并且没有开启tomcat的NIO模式时,可以配合HTTP异步来提升程序性能。尤其是当业务繁重时,提升效果尤其明显。
2、关于服务容器
在基于天花板接口的测试中,综合对比tomcat、jetty、undertow,可以发现undertow相对性能更高点。但此结果并不一定准确,因为测试方案里只进行了很简单的参数调整,以及并没有针对实际业务代码进行测试。不过源码我已提供,有兴趣的可以实际测试下。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
Solidity陷阱:以太坊的随机数生成
title: Solidity陷阱:以太坊的随机数生成 Solidity是一种相当新的语言,因为没有代码是完美的,它包含与代码相关的问题以及你希望用它完成的任务。本文将指导你使用随机数作为以太坊智能合约的输入时的最佳实践和陷阱。 Solidity随机数生成 Solidity无法创建随机数。实际上,每个创建随机数的算法都是伪随机的——没有语言能够创建完全随机的数字。Solidity的问题在于复杂的算法成本太高,因此使用了更基本的解决方案。除此之外,Solidity代码应该是确定性的,因为它将在多个节点上运行。我们需要一种能够生成一次随机数的算法,并在多个节点上使用它。像时钟时间这样的东西不能用于生成随机数,因此我们必须查看其他选项。作为开发人员,你应该了解此问题,因为攻击者能够在某些特定情况下预测结果。 最常用的算法之一是“线性同余发生器”(LCG)。它是最古老的算法之一,快速且易于理解。LCG是嵌入式系统的一个很好的选择,因为它们的内存有限。但是,它不适合加密安全应用程序。虽然,这仍然在智能合约中使用,因为快速算法在气体成本方面实施起来便宜得多。 算法本身执行以下步骤: 接受输入。 在...
-
下一篇
美团DB数据同步到数据仓库的架构与实践
背景 在数据仓库建模中,未经任何加工处理的原始业务层数据,我们称之为ODS(Operational Data Store)数据。在互联网企业中,常见的ODS数据有业务日志数据(Log)和业务DB数据(DB)两类。对于业务DB数据来说,从MySQL等关系型数据库的业务数据进行采集,然后导入到Hive中,是进行数据仓库生产的重要环节。 如何准确、高效地把MySQL数据同步到Hive中?一般常用的解决方案是批量取数并Load:直连MySQL去Select表中的数据,然后存到本地文件作为中间存储,最后把文件Load到Hive表中。这种方案的优点是实现简单,但是随着业务的发展,缺点也逐渐暴露出来: 性能瓶颈:随着业务规模的增长,Select From MySQL -> Save to Localfile -> Load to Hive这种数据流花费的时间越来越长,无法满足下游数仓生产的时间要求。 直接从MySQL中Select大量数据,对MySQL的影响非常大,容易造成慢查询,影响业务线上的正常服务。 由于Hive本身的语法不支持更新、删除等SQL原语,对于MySQL中发生Updat...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- MySQL数据库在高并发下的优化方案
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8编译安装MySQL8.0.19