文档章节

后续之《SpringBoot服务器压测对比(jetty、tomcat、undertow)》

尚浩宇
 尚浩宇
发布于 12/07 11:41
字数 1740
阅读 2499
收藏 80

一、前言

    昨天发了一个《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相对性能更高点。但此结果并不一定准确,因为测试方案里只进行了很简单的参数调整,以及并没有针对实际业务代码进行测试。不过源码我已提供,有兴趣的可以实际测试下。

© 著作权归作者所有

共有 人打赏支持
尚浩宇
粉丝 63
博文 143
码字总数 115191
作品 3
朝阳
程序员
私信 提问
加载中

评论(12)

尚浩宇
尚浩宇

引用来自“freezingsky”的评论

我tomcat和undertow 在2核,4G的情况下,吞吐量,tomcat为3700+,undertow为4300+.请求量为10万.
你这设备配置应该不止这个数啊.

引用来自“Maxwell1987”的评论

瓶颈到了,spring boot 内嵌的 tomcat 差不多 300% 就到极限了,更多的 C 没用。

引用来自“尚浩宇”的评论

对,tomcat作为一个重量级人物,还是不适合内嵌这种场景

引用来自“Maxwell1987”的评论

实际上你测试的 3 种容器都在同一个量级上,谈不上谁重量谁轻量。内嵌也没有关系。你可以测试一下 webflux,用 netty 的也差不多。这瓶颈并不是 tomcat 的。
我记得webflux并不能提高性能,他只是在有限的资源下提高系统的吞吐量和伸缩性,本质上也是一个NIO模式
Maxwell1987
Maxwell1987

引用来自“freezingsky”的评论

我tomcat和undertow 在2核,4G的情况下,吞吐量,tomcat为3700+,undertow为4300+.请求量为10万.
你这设备配置应该不止这个数啊.

引用来自“Maxwell1987”的评论

瓶颈到了,spring boot 内嵌的 tomcat 差不多 300% 就到极限了,更多的 C 没用。

引用来自“尚浩宇”的评论

对,tomcat作为一个重量级人物,还是不适合内嵌这种场景
实际上你测试的 3 种容器都在同一个量级上,谈不上谁重量谁轻量。内嵌也没有关系。你可以测试一下 webflux,用 netty 的也差不多。这瓶颈并不是 tomcat 的。
尚浩宇
尚浩宇

引用来自“orpherus”的评论

方法调用10000次是jvm触发jit优化的阈值,所以测试前先预热个10万次,才更接近真实场景。另外tomcat还支持apr native优化,开与不开是有差异的。

正常情况,4核i5机器跑hello world,tomcat应该跑到20000以上rps才及格。
每次的数据都是重复执行10遍,选取的最大值。我这服务器本身硬件老旧,程序优化手段也很简单,主要是想看下常见优化手段下各个服务容器的反应
尚浩宇
尚浩宇

引用来自“freezingsky”的评论

我tomcat和undertow 在2核,4G的情况下,吞吐量,tomcat为3700+,undertow为4300+.请求量为10万.
你这设备配置应该不止这个数啊.

引用来自“Maxwell1987”的评论

瓶颈到了,spring boot 内嵌的 tomcat 差不多 300% 就到极限了,更多的 C 没用。
对,tomcat作为一个重量级人物,还是不适合内嵌这种场景
尚浩宇
尚浩宇

引用来自“freezingsky”的评论

我tomcat和undertow 在2核,4G的情况下,吞吐量,tomcat为3700+,undertow为4300+.请求量为10万.
你这设备配置应该不止这个数啊.
看参数还可以,但是服务器本身已经不行了,PowerEdge R710,本身就是我从线上淘汰下来的机器攒机出来的
尚浩宇
尚浩宇

引用来自“局长”的评论

红薯又要翻牌了
😜
orpherus
orpherus
方法调用10000次是jvm触发jit优化的阈值,所以测试前先预热个10万次,才更接近真实场景。另外tomcat还支持apr native优化,开与不开是有差异的。

正常情况,4核i5机器跑hello world,tomcat应该跑到20000以上rps才及格。
Maxwell1987
Maxwell1987

引用来自“freezingsky”的评论

我tomcat和undertow 在2核,4G的情况下,吞吐量,tomcat为3700+,undertow为4300+.请求量为10万.
你这设备配置应该不止这个数啊.
瓶颈到了,spring boot 内嵌的 tomcat 差不多 300% 就到极限了,更多的 C 没用。
f
freezingsky
我tomcat和undertow 在2核,4G的情况下,吞吐量,tomcat为3700+,undertow为4300+.请求量为10万.
你这设备配置应该不止这个数啊.
cxd520913
cxd520913
厉害
SpringBoot服务器压测对比(jetty、tomcat、undertow)

1、本次对比基础环境信息如下: springboot版本1.5.10 centos虚机4c6G,版本7.4 centos实机2u16c40G,版本7.4,虚机运行在实机上 ab版本2.3 jprofiler版本9.1.1 2、压测接口说明 天花板:指的...

尚浩宇
12/06
0
0
springboot情操陶冶-初识springboot

前言:springboot由于其轻便和去配置化等的特性已经被广泛应用,基于时代潮流以及不被鄙视,笔者于是开辟此篇开始认识springboot 前话 springboot是基于spring而开发的轻量级框架,所以在学习...

南柯问天
07/24
0
0
springboot的内存占用

公司现在的项目都使用springboot,上线之后发现内存都最少用了100多M,我试了一个什么都没有的项目,只有一个启动类的springboot项目,启动起来也需要100多M,我使用jvisualvm查看,堆内存使...

迷途的码农
2017/10/08
502
3
SpringBoot-01:什么是SpringBoot?

------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- SpringBoot: Spring Boot可以轻松创建独立的,生产级的基于Spring的应用程序,您可以“运行”。 SpringBoot对Spring平台和...

晨曦dawn
06/22
0
0
SpringBoot 2.0 系列001 -- 入门介绍以及相关概念

SpringBoot 2.0 系列001 -- 入门介绍以及相关概念 什么是SpringBoot? 项目地址:http://projects.spring.io/spring-boot/ SpringBoot介绍 Spring Boot使开发独立的,产品级别的基于Spring的...

路上有你0314
05/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

iOS补位动画、沙漏效果、移动UITableViewCell、模拟贪吃蛇、拖拽进度等源码

iOS精选源码 JHAlertView - 一款黑白配色的HUD之沙漏效果 继承UIButton的自定义按钮SPButton 用递归算法实现iOS补位动画 iOS 长按移动UITableViewCell JHLikeButton - 有趣的点赞动画 兼容X...

Android爱开源
14分钟前
0
0
08.Beetl自定义方法以及直接访问java类方法---《Beetl视频课程》

本期视频实现了发布评论时间自定义显示; 内容简介:使用了自定义方法以及直接访问java方法实现了发布时间自定义显示 一起学beetl目录:https://my.oschina.net/u/1590490?tab=newest&catal...

Gavin-King
15分钟前
0
0
上币至iamToken

https://github.com/consenlabs/token-profile 点击Fork按钮,插入到自己的github项目中 cd /Users/shijun/Desktop/blockChain/iamToken git clone https://github.com/yellmi1983/token-pro......

八戒八戒八戒
17分钟前
0
0
spark——sparkCore源码解析之RangePartitioner

HashPartitioner分区可能导致每个分区中数据量的不均匀。而RangePartitioner分区则尽量保证每个分区中数据量的均匀,将一定范围内的数映射到某一个分区内。分区与分区之间数据是有序的,但分...

freeli
17分钟前
1
0
常用的ES6语法

什么是ES6?   ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。Mozilla公司将在这个标准的基础上,推出JavaScript 2.0。   ECMAScript和JavaScr...

peakedness丶
21分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部