昨天發了一個《SpringBoot服務器壓測對比(jetty、tomcat、undertow)》,本是工做的一個筆記,沒想到被紅薯翻牌了(榮幸之至)。看了OSCer的回覆,感受須要從新梳理下,由於確實存在描述不清和不合理的配置。java
這篇博客的目的,不是複述上一篇博客,而是儘可能規範的去作一次壓測對比,而且可以清晰的描述出過程和結果。git
爲了保證儘可能少的干擾,這裏再也不在虛擬機上運行服務,而是直接在物理機上運行服務,而且在這臺物理機上安裝ab工具。web
服務器配置是2個CPU,單個CPU8核,總共內存40G,1T的RAID5機械硬盤。服務器安裝的系統是Centos7.5,系統優化同《Centos7高併發優化》所述。但額外的,因工做須要,這臺物理機上有6個虛機,是不能關閉的。如下是簡單的top展現:spring
感謝@TGVvbmFyZA 的建議,測試項目再也不使用生產項目,而是從Springboot官網打包2.x版本的項目,這樣的目的是減小生產項目中沒必要要的依賴,從而避免沒必要要的開銷。如下是簡單的項目介紹: apache
序號 | 名稱 | 版本 |
1 | springboot | 2.1.1 |
2 | java | 1.8 |
我已將項目放到Gitee,地址:https://gitee.com/loveliyiyi/test4servertomcat
如下貼出關鍵代碼,以便更好理解。 springboot
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 ""; }); } }
不一樣的服務器容器優化參數均不一致,如下是本次測試主要優化的地方:bash
序號 | 服務容器 | 優化參數 |
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會影響必定得性能。如下是壓測步驟:
一、使用tomcat,壓測兩個接口,按不一樣併發訪問10000次,而後不斷調整參數,獲取最大結果。由此可得出純tomcat和tomcat+http異步的結果。
二、使用jetty,壓測兩個接口,按不一樣併發訪問10000次,而後不斷調整參數,獲取最大結果。由此可得出純jetty和jetty+http異步的結果。
三、使用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相對性能更高點。但此結果並不必定準確,由於測試方案裏只進行了很簡單的參數調整,以及並無針對實際業務代碼進行測試。不過源碼我已提供,有興趣的能夠實際測試下。