Servlet 3 性能調優

Servlet 3 早在 2011 年推出,但很多 web 項目還是使用 Servlet 2.5。這些 web 項目業務相對較重、單機負載相對較低,Servlet 2.5 由于更少切換線程比 Servlet 3 更加穩定。

隨著微服務的發展,web 層不斷演進,涌現出越來越多的 API 網關。API 網關將 web 層的業務剝離開,專注于安全防護和路由轉發。這種重 IO 輕 CPU 的場景非常適合使用 Servlet 3。

通常異步 Servlet 項目中有 3 類線程池:Tomcat IO 工作線程池、業務線程池、RPC 線程池。

下面介紹 Servlet 優化的五個階段,這五個階段大致分為三類優化手段:線程隔離、無鎖處理和更換容器。

第一階段:純同步

第一階段采用同步 Servlet,Tomcat 線程進入業務代碼并執行預處理、RPC 調用、結果處理
壓測到 1000 QPS 時 AVG(20)、99 線(70)、999 線(75),整體平穩

第二階段:偽異步

異步 Servlet 中通過 servletRequest.startAsync 開啟異步,asyncContext.dispatch 重新分發請求、asyncContext.complete 結束異步。Spring MVC 的異步是先開啟異步、執行業務、重新分發請求。這種方式是為了兼容 Spring MVC 的同步實現,但是由于兩次分發導致代碼更復雜、并可能對 Servlet 帶來更大的壓力。

在第二階段的時候采用類似的實現:

  1. Tomcat 線程進入業務代碼并預處理請求
  2. Tomcat 線程開啟異步并異步請求 RPC 服務
  3. RPC 回調后重新分發請求
  4. Tomcat 線程進入業務代碼并處理請求結果

壓測到 1000 QPS 時 AVG(18)、99 線(56)、999 線(60),整體平穩,異步占優
壓測到 1400 QPS 時 AVG(23)、99 線(80)、999 線(85),整體平穩,異步占優
壓測到 2000 QPS 時 AVG(32)、99 線(300)、999 線(320),波動較大

第三階段:全異步

項目在第三階段的時候采用全異步:

  1. Tomcat 線程進入業務代碼并開啟異步
  2. Tomcat 線程提交業務線程并返回
  3. 業務線程預處理并調用 RPC 服務
  4. RPC 回調后提交業務線程
  5. 業務線程處理請求結果并結束異步

壓測到 2500 QPS 時 AVG(44)、99 線(83)、999 線(85),整體平穩,時有抖動
壓測到 3000 QPS 時 AVG(70)、99 線(180)、999 線(190),整體平穩,時有抖動

第四階段:異步優化

業界 4 核 8 g 異步 Servlet 的機器吞吐量能夠達到 1w+ QPS

1.觀察機器在壓測時的性能指標,QPS 3000 時出現 full gc

2.壓測結束后 Dump 機器內存后發現無大對象,但是有大量 byte [] 和 char [] 對象

3.使用 JProfiler 分析 byte [] 的來源,可能來自 Tomcat 的 IO

在對比 Tomcat 線程數后猜測,可能是 Tomcat 線程池打滿所致。同時在 Tomcat 日志中也出現大量隊列已滿的報錯

4.嘗試調整 Tomcat 線程池配置:增加線程數量、采用 Http11Nio2Protocol 處理協議。調整后壓測吞吐量沒有提升。https://renwole.com/archives/357

<Executor
 name="tomcatThreadPool"
 namePrefix="catalina-exec-"
 maxThreads="500"
 minSpareThreads="30"
 maxIdleTime="60000"
 prestartminSpareThreads = "true"
 maxQueueSize = "100"
/>
<Connector
 executor="tomcatThreadPool"
 port="8080"
 protocol="org.apache.coyote.http11.Http11Nio2Protocol"
 connectionTimeout="60000"
 maxConnections="10000"
 redirectPort="8443"
 enableLookups="false"
 acceptCount="100"
 maxPostSize="10485760"
 maxHttpHeaderSize="8192"
 compression="on"
 disableUploadTimeout="true"
 compressionMinSize="2048"
 acceptorThreadCount="2"
 URIEncoding="utf-8"
 processorCache="20000"
 tcpNoDelay="true"
 connectionLinger="5"
 server="Server Version 11.0"
 />

5.修改業務線程池大小
壓測到 5000 QPS 時 AVG(59)、99 線(130)、999 線(145),整體平穩

6.修改調用下游服務的方式,基于回調 => 同步

7.對比業務各階段耗時,增加服務調用線程池線程
壓測到 6000 QPS 時高點 AVG(348)、99 線(500)、999 線(1000),整體平穩

8.異步 Servlet 開啟異步后超時自動結束請求,RPC 在回調時如果已經超時會報狀態異常,因此對 onTimeout 和 onComplete 加上同步鎖

9.移除 RPC 調用,mock 服務返回結果
壓測到 10000 QPS 時高點 AVG(12)、99 線(504)、999 線(1000),CPU 幾乎打滿

10.調整業務線程組,預處理和調用服務使用同一線程、RPC 回調和處理返回結果使用同一線程,弱化 CPU 輪轉。壓測到高點時開始出現線程阻塞
壓測到 6000 QPS 時高點 AVG(8)、99 線(35)、999 線(1000),CPU 幾乎打滿

11.縮短 RPC 服務超時時間 200 -> 50
壓測到 4000 時開始出現線程阻塞

12.移除 AsyncContext 監聽中 onTimeout 和 onComplete 上的同步鎖

13.使用 servlet 3.1 nio,注冊 reader listener 和 write listener 異步讀寫

壓測到 7000 QPS 時高點 AVG(10)、99 線(30)、999 線(1000)

第四階段總結:

  1. 異步 IO 能一定程度上提高并發,在傳輸量不大的情況下提高并不明顯
  2. 高并發同步調用會阻塞 IO 線程
  3. Tomcat 內部沒有復用 bytebuffer 導致請求量大時新生代 gc 頻繁,最后引起服務超時,日志阻塞等一系列問題

第五階段:Jetty 容器

Jetty 底層對 ByteBuffer 對象的復用和線程池的處理有更好的優化。
在第五階段,更換 Servlet 容器為 Jetty 進行調優。
壓測到 11000 QPS 時高點 AVG(40)、99 線(90)、999 線(140),整體平穩

第五階段總結:

  1. 在高并發的場景中,Jetty 的性能比 Tomcat 要強,耗時曲線非常平穩
  2. 使用 Jetty 容器后,10000 QPS 時 AVG(5)、99 線(20)、999 線(20
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容