後續之《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 [email protected]
 * @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相對性能更高點。但此結果並不一定準確,因爲測試方案裏只進行了很簡單的參數調整,以及並沒有針對實際業務代碼進行測試。不過源碼我已提供,有興趣的可以實際測試下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章