記一次Full GC導致的線上問題

導火索

nginx報502
先查看了一下ng的錯誤日志篮灼,有如下兩種類型的報錯:

 [error] 24826#0: *32529323 upstream prematurely closed connection while reading response header from upstream
 [error] 24826#0: *32502388 no live upstreams while connecting to upstream

第一個錯誤是由于upstream還沒有應(yīng)答給用戶時空另,用戶斷掉連接造成的魄幕,大概率為客戶端連接超時自動斷開了陕贮。
第二個錯誤就比較迷了匣屡,這個錯誤是指找不到存活的后端server,但是網(wǎng)上查看引起這個錯誤的原因是多種多樣的女气。

多線并行

由于環(huán)境問題杏慰,取后端應(yīng)用日志比較耗時,在這期間利用如下命令寫了一個shell腳本觀察nginx服務(wù)器的端口連接情況

netstat -n | awk '/^tcp/ {++S[$NF]} END {for (a in S) print a, S[a]}'

通過腳本打印的日志發(fā)現(xiàn),服務(wù)器有10幾秒的時間TIME_WAIT狀態(tài)的端口達到了28232缘滥,如下圖

6a9b8046d1ff80facfcb4d96fa48680.png

通過以下命令查看本地端口范圍配置

cat /proc/sys/net/ipv4/ip_local_port_range

發(fā)現(xiàn)本地可使用的端口個數(shù)剛好為28232


image.png

也正是在這個時間段nginx開始不斷報錯

初步判斷是由于nginx服務(wù)器連接端口被用盡導致無法創(chuàng)建新的連接從而報錯

于是乎我找了一臺測試服務(wù)器做了個壓測轰胁,一分鐘壓了3W個請求,果然在請求到達2W+的時候ng開始報錯了朝扼。然而錯誤信息卻是如下:

 [alert] 28637#0: *255914 socket() failed (24: Too many open files) while connecting to upstream

明顯跟我們之前遇到的報錯是有區(qū)別的软吐,同時我們nginx是做了雙中心,兩臺nginx的并發(fā)量存在明顯差異吟税,確都報了相同的錯誤。由此可以判斷并非高并發(fā)導致的服務(wù)器連接端口用盡姿现。

這個時候剛好我們也取下了后端應(yīng)用的日志肠仪,在對日志進行篩查后,發(fā)現(xiàn)了以下的報錯

Caused by: java.io.IOException: Broken pipe
    at sun.nio.ch.FileDispatcherImpl.write0(Native Method) ~[?:1.8.0_171]
    at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47) ~[?:1.8.0_171]
    at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93) ~[?:1.8.0_171]
    at sun.nio.ch.IOUtil.write(IOUtil.java:65) ~[?:1.8.0_171]
    at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471) ~[?:1.8.0_171]
    at org.apache.tomcat.util.net.NioChannel.write(NioChannel.java:136) ~[tomcat-coyote.jar:8.5.55]
    at org.apache.tomcat.util.net.NioBlockingSelector.write(NioBlockingSelector.java:101) ~[tomcat-coyote.jar:8.5.55]
    at org.apache.tomcat.util.net.NioSelectorPool.write(NioSelectorPool.java:157) ~[tomcat-coyote.jar:8.5.55]
    at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.doWrite(NioEndpoint.java:1312) ~[tomcat-coyote.jar:8.5.55]
    at org.apache.tomcat.util.net.SocketWrapperBase.doWrite(SocketWrapperBase.java:692) ~[tomcat-coyote.jar:8.5.55]
    at org.apache.tomcat.util.net.SocketWrapperBase.flushBlocking(SocketWrapperBase.java:645) ~[tomcat-coyote.jar:8.5.55]
    at org.apache.tomcat.util.net.SocketWrapperBase.flush(SocketWrapperBase.java:635) ~[tomcat-coyote.jar:8.5.55]
    at org.apache.coyote.http11.Http11OutputBuffer$SocketOutputBuffer.flush(Http11OutputBuffer.java:646) ~[tomcat-coyote.jar:8.5.55]
    at org.apache.coyote.http11.filters.IdentityOutputFilter.flush(IdentityOutputFilter.java:160) ~[tomcat-coyote.jar:8.5.55]
    at org.apache.coyote.http11.Http11OutputBuffer.flush(Http11OutputBuffer.java:252) ~[tomcat-coyote.jar:8.5.55]
    at org.apache.coyote.http11.Http11Processor.flush(Http11Processor.java:1392) ~[tomcat-coyote.jar:8.5.55]
    at org.apache.coyote.AbstractProcessor.action(AbstractProcessor.java:404) ~[tomcat-coyote.jar:8.5.55]
    at org.apache.coyote.Response.action(Response.java:206) ~[tomcat-coyote.jar:8.5.55]
    at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:326) ~[catalina.jar:8.5.55]
    ... 60 more

這個錯誤是由于tomcat服務(wù)器在應(yīng)答時發(fā)現(xiàn)客戶端連接已經(jīng)關(guān)閉备典,想必是某種原因?qū)е路?wù)器響應(yīng)時間太長异旧,導致客戶端連接超時主動關(guān)閉。

柳暗花明

按照慣例提佣,我們應(yīng)該從以下角度開始排查為何服務(wù)器響應(yīng)會超時:

  • 數(shù)據(jù)庫連接超時吮蛹、數(shù)據(jù)庫鎖
  • 存在慢sql導致sql執(zhí)行超時、數(shù)據(jù)庫連接池阻塞
  • 存在長時間的線程阻塞
  • cpu超載拌屏、io_wait等

通過排查首先排除了數(shù)據(jù)庫方面的問題

監(jiān)控工具也沒有發(fā)現(xiàn)cpu和內(nèi)存異常的信息潮针,cpu load average也沒有異常

在linux下查看cpu和IO問題后,順便查看了一下JVM的內(nèi)存使用情況

使用命令jmap -heap pid 查看如下:

Attaching to process ID 1, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.171-b11

using thread-local object allocation.
Parallel GC with 43 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 17179869184 (16384.0MB)
   NewSize                  = 89128960 (85.0MB)
   MaxNewSize               = 5726273536 (5461.0MB)
   OldSize                  = 179306496 (171.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 4995416064 (4764.0MB)
   used     = 371647312 (354.4304962158203MB)
   free     = 4623768752 (4409.56950378418MB)
   7.439766923086069% used
From Space:
   capacity = 363331584 (346.5MB)
   used     = 341794088 (325.96024322509766MB)
   free     = 21537496 (20.539756774902344MB)
   94.07222026698345% used
To Space:
   capacity = 365428736 (348.5MB)
   used     = 0 (0.0MB)
   free     = 365428736 (348.5MB)
   0.0% used
PS Old Generation
   capacity = 3899129856 (3718.5MB)
   used     = 3334968784 (3180.474075317383MB)
   free     = 564161072 (538.0259246826172MB)
   85.53110327598179% used

突然發(fā)現(xiàn)倚喂,JVM的堆內(nèi)存老年代(Old Generation)高達近4個G每篷,使用率接近90%,嘴里不禁喃喃自語:“該GC了....”端圈,就在這句話脫口而出的時候焦读,腦海中突然靈光乍現(xiàn),GC舱权,Stop the World 矗晃!
趕緊通過jstat -gcutil pid命令查看JVMGC情況

6fd0d284bc7ce6df2120c087c140ac5.png

由于當時是遠程機,所以沒有留下截圖宴倍,實際情況是Full GC進行了9次张症,總共耗時400多秒,平均FGC時間達到了50秒啊楚。(以上截圖已經(jīng)是第一次優(yōu)化后的結(jié)果了)

離了個大譜吠冤,眾所周知,Java程序在GC時會出現(xiàn)Stop the World恭理,這個時候程序處于暫停狀態(tài)

一切都解釋通了拯辙,當FULL GC長時間進行的時候,nginx對應(yīng)用的訪問就會出現(xiàn)以下錯誤

 [error] 24826#0: *32502388 no live upstreams while connecting to upstream

當nginx和后端應(yīng)用建立好連接之后,后端應(yīng)用出現(xiàn)FULL GC涯保,導致長時間掛起诉濒,結(jié)果nginx訪問超時主動關(guān)閉了連接,然后后端應(yīng)用GC完畢之后繼續(xù)處理夕春,當準備返回應(yīng)答信息時未荒,就出現(xiàn)了以下錯誤

Caused by: java.io.IOException: Broken pipe
    at sun.nio.ch.FileDispatcherImpl.write0(Native Method) ~[?:1.8.0_171]
    at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47) ~[?:1.8.0_171]
    at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93) ~[?:1.8.0_171]
    at sun.nio.ch.IOUtil.write(IOUtil.java:65) ~[?:1.8.0_171]
    at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471) ~[?:1.8.0_171]
    at org.apache.tomcat.util.net.NioChannel.write(NioChannel.java:136) ~[tomcat-coyote.jar:8.5.55]

同時如果瀏覽器的連接請求先超時,則會在nginx上出現(xiàn)如下報錯:

[error] 24826#0: *32529323 upstream prematurely closed connection while reading response header from 

為了進一步確定是否為GC STW導致的問題及志,我們選擇重啟了后端應(yīng)用片排,然后持續(xù)進行觀察

果然在沒有出現(xiàn)FGC的情況下,沒有出現(xiàn)任何錯誤速侈, 當錯誤出現(xiàn)之后率寡,發(fā)現(xiàn)已經(jīng)進行了一次FGC,由此基本判斷是由于FGC導致的問題倚搬, 接下來就是優(yōu)化JVM的問題了冶共。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市每界,隨后出現(xiàn)的幾起案子捅僵,更是在濱河造成了極大的恐慌,老刑警劉巖眨层,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庙楚,死亡現(xiàn)場離奇詭異,居然都是意外死亡谐岁,警方通過查閱死者的電腦和手機醋奠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來伊佃,“玉大人窜司,你說我怎么就攤上這事『饺啵” “怎么了塞祈?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長帅涂。 經(jīng)常有香客問我议薪,道長,這世上最難降的妖魔是什么媳友? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任斯议,我火速辦了婚禮,結(jié)果婚禮上醇锚,老公的妹妹穿的比我還像新娘哼御。我一直安慰自己坯临,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布恋昼。 她就那樣靜靜地躺著看靠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪液肌。 梳的紋絲不亂的頭發(fā)上挟炬,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音嗦哆,去河邊找鬼谤祖。 笑死,一個胖子當著我的面吹牛老速,可吹牛的內(nèi)容都是我干的泊脐。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼烁峭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了秕铛?” 一聲冷哼從身側(cè)響起约郁,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎但两,沒想到半個月后鬓梅,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體横堡,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡祠墅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年滨溉,在試婚紗的時候發(fā)現(xiàn)自己被綠了严蓖。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绳匀。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡椿胯,死狀恐怖娩脾,靈堂內(nèi)的尸體忽然破棺而出知市,到底是詐尸還是另有隱情擅耽,我是刑警寧澤活孩,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站乖仇,受9級特大地震影響憾儒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乃沙,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一起趾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧警儒,春花似錦训裆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽汛闸。三九已至,卻和暖如春艺骂,著一層夾襖步出監(jiān)牢的瞬間诸老,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工钳恕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留别伏,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓忧额,卻偏偏與公主長得像厘肮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子睦番,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

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