Tomcat 、Jetty 和 Undertow 對比測試

背景


最近在做壓測 , 同事覺得 Tomcat 不行想要切換 web 服務(wù)器 , 于是我就去網(wǎng)上搜了一些測評結(jié)果 , 不出意外 Tomcat 得到了一致的差評螟碎。抱著懷疑的態(tài)度 , 我決定對 SpringBoot 內(nèi)嵌支持的三款 Servlet 容器 ( Tomcat 楣嘁、JettyUndertow ) 做一個簡單的對比測試 , 測試結(jié)果僅供參考

測試環(huán)境


項目 描述
測試端主機 阿里云ECS(ecs.sn1ne.2xlarge) 8C16G CentOS7.4.1708 Linux Kernel 3.10.0
被測端主機 阿里云ECS(ecs.sn1ne.2xlarge) 8C16G CentOS7.4.1708 Linux Kernel 3.10.0
網(wǎng)絡(luò)環(huán)境 阿里云專有網(wǎng)絡(luò) 內(nèi)網(wǎng)帶寬: 2 Gbps
測試工具 wrk
項目框架 SpringBoot 1.5.10.RELEASE
JDK 1.8.0_191 Java HotSpot(TM) 64-Bit Server VM
測試容器 Tomcat Jetty Undertow

說明:

  • 測試端和被測端分別在兩臺主機上 , 為了避免放在一臺主機上導(dǎo)致互相搶占 CPU 而無法得到真實結(jié)果帆锋。

  • 主角是 Servlet容器 , 所以網(wǎng)絡(luò)環(huán)境不應(yīng)該是這次測試的瓶頸 ( 系統(tǒng)內(nèi)核的 TCP 參數(shù)也要優(yōu)化 ) 吵取。

  • 測試工具用過 wrkab 锯厢、jmeter , 測試的目的是為了獲取被測端的性能 , 但不能因為測試工具的性能瓶頸而埋沒了被測端的真實能力 , 因此選用簡單高效的 wrk ( 下載源碼編譯安裝 ) 皮官。

測試方法


使用最簡單的 HTTP 接口 , 不包含任何業(yè)務(wù)邏輯和數(shù)據(jù)庫操作 , 反映容器的極致性能

@RestController
@RequestMapping("/api")
public class TestController {

    @RequestMapping("/test")
    public String test() {
        return "This is a test result.";
    }

}

使用 wrk 5000 并發(fā)下持續(xù)壓測 10 分鐘 ( 超時時間設(shè)為 30s , 避免超時時間過短帶來的大量錯誤 )

./wrk -t 8 -c 5000 -d 10m -T 30s "http://yourhostip:3000/api/test"

說明:

  • JVM 內(nèi)存設(shè)置為 2G 大小

  • 項目啟動后需要預(yù)熱 ( JIT 編譯、加線程等等 ) 一下才能達到最優(yōu)的性能实辑。

  • 為了避免性能數(shù)據(jù)波動造成的影響 , 每種情況測試 3 遍后取最優(yōu)結(jié)果捺氢。

  • 按理說測試時間越長越能反映真實情況,不過試了 30 分鐘的測試 , 一趟測試下來耗費了一天時間 , 結(jié)果和 10 分鐘的也差不了多少 , 所以還是節(jié)省點時間吧徙菠。

測試結(jié)果


Tomcat 8.0.53 NIO 模式

  • 啟動命令:

    java -Xms2g -Xmx2g -Xmn1g -XX:MaxMetaspaceSize=256m -Xss256k -jar servlet-test-tomcat-8-nio.jar
    
  • 監(jiān)控項:

    wrk 的 CPU 使用率: 161.3% ( 最大 800% )
    Server 的 CPU 使用率: 52.4 us, 13.0 sy,  0.0 ni, 16.8 id,  0.0 wa,  0.0 hi, 17.8 si,  0.0 st
    Server GC 情況:YGC: 870 YGCT: 5.3 FGC:0
    
  • wrk 結(jié)果:

    Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency    86.31ms    7.23ms 778.24ms   88.50%
        Req/Sec     7.25k   420.33    14.55k    72.93%
      34639518 requests in 10.00m, 5.33GB read
      Socket errors: connect 0, read 1253, write 2928, timeout 0
    Requests/sec:  57726.28
    Transfer/sec:      9.09MB
    

Tomcat 8.5.34 NIO 模式

  • 啟動命令:

    java -Xms2g -Xmx2g -Xmn1g -XX:MaxMetaspaceSize=256m -Xss256k -jar servlet-test-tomcat-8.5-nio.jar
    
  • 監(jiān)控項:

    wrk 的 CPU 使用率: 132.3% ( 最大 800% )
    Server 的 CPU 使用率: 60.2 us, 14.1 sy,  0.0 ni, 19.1 id,  0.0 wa,  0.0 hi,  6.5 si,  0.0 st
    Server GC 情況:YGC: 940 YGCT: 5.736 FGC:0
    
  • wrk 結(jié)果:

    Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency    83.43ms    9.79ms   1.70s    96.22%
        Req/Sec     7.51k   408.60    14.48k    73.85%
      35852565 requests in 10.00m, 4.55GB read
      Socket errors: connect 0, read 1165, write 2883, timeout 0
    Requests/sec:  59745.50
    Transfer/sec:      7.76MB
    

Tomcat 8.0.53 APR 模式 ( 服務(wù)器上需要安裝 apr 類庫 )

  • 啟動命令:

    java -Xms2g -Xmx2g -Xmn1g -XX:MaxMetaspaceSize=256m -Xss256k -Djava.library.path=/usr/local/apr/lib -jar servlet-test-tomcat-8-apr.jar
    
  • 監(jiān)控項:

    wrk 的 CPU 使用率: 183.4% ( 最大 800% )
    Server 的 CPU 使用率: 69.5 us, 13.7 sy,  0.0 ni,  3.7 id,  0.0 wa,  0.0 hi, 13.1 si,  0.0 st
    Server GC 情況:YGC: 1224 YGCT: 6.251 FGC:0
    
  • wrk 結(jié)果:

    Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency    61.71ms   71.59ms   7.29s    99.87%
        Req/Sec    10.36k   441.68    18.63k    78.23%
      49480257 requests in 10.00m, 7.61GB read
      Socket errors: connect 0, read 1388, write 814, timeout 0
    Requests/sec:  82453.62
    Transfer/sec:     12.99MB
    

Jetty 9.4.8.v20171121

  • 啟動命令:

    java -Xms2g -Xmx2g -Xmn1g -XX:MaxMetaspaceSize=256m -Xss256k -jar servlet-test-jetty.jar
    
  • 監(jiān)控項:

    wrk 的 CPU 使用率: 11.3% ( 最大 800% )
    Server 的 CPU 使用率: 98.6 us,  0.5 sy,  0.0 ni,  0.5 id,  0.0 wa,  0.0 hi,  0.4 si,  0.0 st
    Server GC 情況:YGC: 640 YGCT: 6.541 FGC:0
    
  • wrk 結(jié)果:

    Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency   126.01ms  435.50ms  29.95s    90.64%
        Req/Sec   206.88    127.12     1.03k    70.75%
      978373 requests in 10.00m, 128.76MB read
      Socket errors: connect 0, read 95571, write 7191, timeout 331
    Requests/sec:   1630.39
    Transfer/sec:    219.72KB
    

Undertow 1.4.22.Final

  • 啟動命令:

    java -Xms2g -Xmx2g -Xmn1g -XX:MaxMetaspaceSize=256m -Xss256k -jar servlet-test-undertow.jar
    
  • 監(jiān)控項:

    wrk 的 CPU 使用率: 32.6% ( 最大 800% )
    Server 的 CPU 使用率: 93.6 us,  2.4 sy,  0.0 ni,  1.5 id,  0.0 wa,  0.0 hi,  2.5 si,  0.0 st
    Server GC 情況:YGC: 370 YGCT: 1.684 FGC:0
    
  • wrk 結(jié)果:

    Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency   354.95ms  138.95ms   1.93s    75.08%
        Req/Sec     1.77k   199.04     4.19k    72.85%
      8471058 requests in 10.00m, 1.28GB read
      Socket errors: connect 0, read 1601, write 2882, timeout 0
    Requests/sec:  14117.10
    Transfer/sec:      2.18MB
    

Undertow 1.4.22.Final 配置線程數(shù)

  • 啟動命令:

    java -Xms2g -Xmx2g -Xmn1g -XX:MaxMetaspaceSize=256m -Xss256k -Dserver.undertow.io-threads=16 -Dserver.undertow.worker-threads=256 -jar servlet-test-undertow.jar
    
  • 監(jiān)控項:

    wrk 的 CPU 使用率: 33.3% ( 最大 800% )
    Server 的 CPU 使用率: 92.1 us,  2.4 sy,  0.0 ni,  2.3 id,  0.0 wa,  0.0 hi,  3.2 si,  0.0 st
    Server GC 情況:YGC: 367 YGCT: 2.23 FGC:0
    
  • wrk 結(jié)果:

    Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency   391.49ms  333.83ms   3.23s    60.47%
        Req/Sec     1.76k   235.55     4.51k    69.41%
      8389131 requests in 10.00m, 1.27GB read
      Socket errors: connect 0, read 3987, write 3486, timeout 0
    Requests/sec:  13980.36
    Transfer/sec:      2.16MB
    

Undertow 2.0.15.Final

  • 啟動命令:

    java -Xms2g -Xmx2g -Xmn1g -XX:MaxMetaspaceSize=256m -Xss256k -jar servlet-test-undertow2.jar
    
  • 監(jiān)控項:

    wrk 的 CPU 使用率: 31.6% ( 最大 800% )
    Server 的 CPU 使用率: 90.0 us,  2.6 sy,  0.0 ni,  4.1 id,  0.0 wa,  0.0 hi,  3.3 si,  0.0 st
    Server GC 情況:YGC: 361 YGCT: 2.676 FGC:0
    
  • wrk 結(jié)果:

    Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency   368.09ms   17.14ms 942.66ms   97.28%
        Req/Sec     1.70k   164.17     4.01k    76.01%
      8118614 requests in 10.00m, 1.22GB read
      Socket errors: connect 0, read 686, write 1453, timeout 0
    Requests/sec:  13530.04
    Transfer/sec:      2.09MB
    

測試結(jié)果分析


Servlet 容器 QPS QPS / GC 次數(shù)
Tomcat 8.0.53 NIO 模式 57726.28 57726.28 / 870 = 66.352
Tomcat 8.5.34 NIO 模式 59745.50 59745.50 / 940 = 63.559
Tomcat 8.0.53 APR 模式 82453.62 ( 最優(yōu) ) 82453.62 / 1224 = 67.364
Jetty 9.4.8.v20171121 1630.39 ( 最差 ) 1630.39 / 640 = 2.547
Undertow 1.4.22.Final 14117.10 14117.10 / 370 = 38.154
Undertow 1.4.22.Final 配置線程數(shù) 13980.36 13980.36 / 367 = 38.094
Undertow 2.0.15.Final 13530.04 13530.04 / 361 = 37.479
  • 先說結(jié)果: Tomcat APR 模式 "最優(yōu)" , Jetty "最差" , Undertow 也沒有想象中的碾壓 Tomcat

  • Tomcat NIO 模式 壓力剛上來的時候 CPU 會用滿 , 穩(wěn)定后基本會留有 10% 以上的空閑

  • Jetty 采用的默認配置 , 才 2k 不到的 QPS 確實有點出乎意料的 , 需要配置后做進一步的測試對比

  • Undertow 提供的配置項很少 , 只有 線程數(shù)緩沖大小 , 加大 線程數(shù) 后也沒能提升性能讯沈。本次測試中 Undertow2.0 版本也沒有性能上的提升。

  • Tomcat8.5 相對于 Tomcat8.0 應(yīng)該有性能上的提升 , 由于系統(tǒng)中安裝的 apr 庫的版本問題沒有測試 Tomcat8.5+APR 的性能 ( Tomcat 版本和 apr 版本要對應(yīng) )

  • 默認線程數(shù): Undertow8 ( CPU 核心數(shù) ) 個 IO 線程 + 64 ( 8 * IO 線程數(shù) ) 個 WORK 線程, TomcatJetty 均在 200 左右婿奔。因為都用的 NIO , 所以調(diào)大線程數(shù)效果不大 , 反而帶來 CPU上下文切換內(nèi)存消耗 ( -Xss ) 的問題

  • 聽人說 Undertow 在正常運行中會莫名其妙掛掉 , 具體原因還不清楚

優(yōu)化


  • JVM 參數(shù)

    曾經(jīng)我也比較信奉所謂的 標準參數(shù) , 然而按照上述方法單獨對 Tomcat 進行對比測試后并沒有得到所謂的 "參數(shù)調(diào)優(yōu)" 的效果, 所以還是 針對實際運行情況再做調(diào)整吧缺狠。
    主要幾類配置項有:

    1. -server

    2. 內(nèi)存 ( -Xms -Xmx -Xmn -Xss )

    3. 垃圾回收器組合

    4. GC 相關(guān)參數(shù) ( 打印日志 / DisableExplicitGC /ExplicitGCInvokesConcurrent / 定時 GC )

  • Connector 運行模式

    Tomcat ConnectorBIONIO 萍摊、APR 三種運行模式 ( 可以看下這篇 文章 ) , 雖然 APR 模式性能最好 ( 不絕對 ) , 但也帶來了維護上的成本 , 所以還是那句話 —— 針對實際的業(yè)務(wù)場景選擇

  • 項目運行參數(shù)

    SpringBoot 中幾個容器的可配置項都在 org.springframework.boot.autoconfigure.web.ServerProperties 這個類中, 一般默認就行了, 遇到問題再調(diào)整 ( Tomcat 相關(guān)配置可以看 這里 )

結(jié)語


  • 本次測試結(jié)果和大部分網(wǎng)上的測試正好相反挤茄。

    網(wǎng)上的測試:在一臺機器上跑 , 用例并發(fā)量比較小 , 得到的 QPS 也比較低 ( 幾百的數(shù)值而且比較接近 ) ,也沒有說明測試使用的機器配置和容器版本 , 只是簡單的把 Tomcat 歸類為性能最差冰木。這樣的測試結(jié)論我認為是很不可靠的穷劈。

    時間有限 , 以上只是部分的測試用例 , 實際可以組合的情況 ( 服務(wù)器配置、容器版本踊沸、實際業(yè)務(wù)代碼等等 ) 多了去了 , 所以再強調(diào)一遍 —— 本次測試結(jié)果僅供參考 歇终。

  • 有人可能會奇怪本次測試的意義?

    一般服務(wù)器上會部署多個應(yīng)用 , 不會讓一個應(yīng)用把所有 CPU 都吃滿 , 而且一般線上應(yīng)用也不會是這么簡單的接口 , 瓶頸往往是在一些復(fù)雜的業(yè)務(wù)邏輯和數(shù)據(jù)庫上 , 網(wǎng)上也有提到三種容器使用的業(yè)務(wù)場景也有所不同逼龟。

    我想說的是 , 本次測試純粹是測試容器的性能 , 空跑的結(jié)果都擺在這了 , 跑業(yè)務(wù)的話性能難道能更好评凝?如果 Jetty 真的如測試中那么差 , 還會有人用它跑高并發(fā)的項目嗎?

    所以 , 本文只是提供一種測試思路 , 有疑問就多動動手進行論證 , 在沒有親自實踐過的情況下都不應(yīng)該輕易下"絕對"的結(jié)論腺律。


轉(zhuǎn)載請注明出處:http://www.reibang.com/p/f7cb40a8ce22

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末奕短,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子匀钧,更是在濱河造成了極大的恐慌翎碑,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件之斯,死亡現(xiàn)場離奇詭異日杈,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門达椰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來翰蠢,“玉大人,你說我怎么就攤上這事啰劲×翰祝” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵蝇裤,是天一觀的道長廷支。 經(jīng)常有香客問我,道長栓辜,這世上最難降的妖魔是什么恋拍? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮藕甩,結(jié)果婚禮上施敢,老公的妹妹穿的比我還像新娘。我一直安慰自己狭莱,他們只是感情好僵娃,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著腋妙,像睡著了一般默怨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上骤素,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天匙睹,我揣著相機與錄音,去河邊找鬼济竹。 笑死痕檬,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的送浊。 我是一名探鬼主播谆棺,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼罕袋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起碍岔,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤浴讯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蔼啦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體榆纽,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了奈籽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饥侵。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖衣屏,靈堂內(nèi)的尸體忽然破棺而出躏升,到底是詐尸還是另有隱情,我是刑警寧澤狼忱,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布膨疏,位于F島的核電站,受9級特大地震影響钻弄,放射性物質(zhì)發(fā)生泄漏佃却。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一窘俺、第九天 我趴在偏房一處隱蔽的房頂上張望饲帅。 院中可真熱鬧,春花似錦瘤泪、人聲如沸灶泵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丘逸。三九已至,卻和暖如春掀宋,著一層夾襖步出監(jiān)牢的瞬間深纲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工劲妙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留湃鹊,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓镣奋,卻偏偏與公主長得像币呵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子侨颈,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 一余赢、Jetty目錄剖析 bin:可執(zhí)行腳本文件demo- base:etc:Jetty模塊定義的XML配置文件的目...
    高廣超閱讀 3,969評論 0 32
  • 常見的http服務(wù)器有apache,nginx哈垢,iis妻柒,tomcat等。HTTP服務(wù)器本質(zhì)上也是一種應(yīng)用程序——它...
    可樂愛上咖啡閱讀 3,973評論 1 49
  • 從三月份找實習(xí)到現(xiàn)在耘分,面了一些公司举塔,掛了不少绑警,但最終還是拿到小米、百度央渣、阿里计盒、京東、新浪芽丹、CVTE北启、樂視家的研發(fā)崗...
    時芥藍閱讀 42,192評論 11 349
  • 一個服務(wù)的實際并發(fā)量收到很多方面因素的影響,大致歸類一下如下: 1志衍、數(shù)據(jù)庫暖庄,這是web項目中最常見的瓶頸,解決方法...
    進擊的胖達閱讀 8,316評論 0 6
  • 美麗鄉(xiāng)村在陜州區(qū)宮前鄉(xiāng)中楼肪,多彩課堂我們在行動培廓。 本周,是我參與雙師課堂的助學(xué)實踐的第1周春叫。 這一周的周二(9月4日...
    三門峽745沈莉紅閱讀 519評論 2 14