Java應(yīng)用服務(wù)器性能問題分析

常見問題

一卖氨、內(nèi)存飆高

歸根結(jié)底,都是代碼中某一刻的內(nèi)存數(shù)據(jù)過高引起服務(wù)器內(nèi)存增加残炮。

  1. 文件導(dǎo)入和導(dǎo)出韭赘,針對(duì)文件的讀寫代碼不合理大數(shù)據(jù)常駐內(nèi)存;或者導(dǎo)入/導(dǎo)出并發(fā)量較大势就。
  2. 存在大表的全表查詢(或者多表級(jí)聯(lián)笛卡爾積查詢)泉瞻,查出的結(jié)果集常駐內(nèi)存脉漏;或者某表查詢數(shù)據(jù)量較大且并發(fā)數(shù)過大(一次查詢數(shù)據(jù)量*并發(fā)數(shù))。
  3. 類對(duì)象實(shí)例化使用后未釋放或者其它臨時(shí)數(shù)據(jù)未釋放袖牙。

二侧巨、CPU飆高

  1. 某些線程在做無阻塞的運(yùn)算,簡單的例子while(true)中不停的做運(yùn)算贼陶,沒有任何阻塞刃泡。寫程序時(shí)巧娱,如果需要做很久的計(jì)算碉怔,可以適當(dāng)將程序sleep下。
  2. 線程上下文切換禁添、當(dāng)啟動(dòng)了很多線程撮胧,而這些線程都處于不斷的阻塞狀態(tài)(鎖等待、IO等待等)和執(zhí)行狀態(tài)的變化過程中老翘。當(dāng)鎖競爭激烈時(shí)芹啥,很容易出現(xiàn)這種情況。(文件讀寫未使用NIO等)
  3. 序列化和反序列操作過于頻繁或者目標(biāo)數(shù)據(jù)量較大導(dǎo)致資源長時(shí)間占用铺峭。(xml/json)
  4. 頻繁GC(內(nèi)存異常飆高導(dǎo)致)墓怀,訪問量高時(shí),有可能造成頻繁的GC卫键、甚至FGC傀履。當(dāng)調(diào)用量大時(shí),內(nèi)存分配過快莉炉,就會(huì)造成GC線程不停的執(zhí)行钓账,導(dǎo)致CPU飆高。
  5. 加密絮宁、解密梆暮。
  6. 正則表達(dá)式校驗(yàn),大概原因是:Java 正則表達(dá)式使用的引擎實(shí)現(xiàn)是 NFA 自動(dòng)機(jī)绍昂,這種引擎在進(jìn)行字符匹配會(huì)發(fā)生回溯(backtracking)啦粹。

三、客戶端請(qǐng)求阻塞

服務(wù)器CPU和內(nèi)存資源看上去正常窘游,通過JVM監(jiān)控器發(fā)現(xiàn)很多Blocked請(qǐng)求線程唠椭;以下幾個(gè)方法請(qǐng)勿出現(xiàn)在生產(chǎn)代碼中,請(qǐng)求并發(fā)量大的情況下张峰,很容導(dǎo)致請(qǐng)求線程阻塞泪蔫。

  1. System.out.println(XX)
  2. logger.debug()
  3. e.printStackTrace()
  4. DefaultHttpClient.execute()未設(shè)置連接超時(shí)時(shí)間。

如何定位原因

一喘批、CPU和內(nèi)存情況分析

  1. 非容器部署時(shí)撩荣,通過top命令查看進(jìn)程占用的CPU和內(nèi)存資源铣揉,找出占用高的進(jìn)程。

    image.png
  2. docker容器部署時(shí)餐曹,通過 “docker stats <容器id或者名稱>”查看cpu和內(nèi)存占用情況逛拱。

    imagef7594.png
  3. 通過jvisualVM或者JConsole查看JVM的CPU、內(nèi)存和線程情況台猴,如果是CPU飆高或者線程阻塞需要dump線程信息定位問題代碼朽合。

    image89810.png
    image702ba.png
  4. 線程dump分析,如果開發(fā)人員能力經(jīng)驗(yàn)不足以肉眼分析定位問題饱狂,將dump出來的內(nèi)容拷貝到txt文件中曹步,訪問在線分析平臺(tái)http://fastthread.io/ ,上傳dump文件休讳,點(diǎn)擊分析按鈕讲婚,等待一小會(huì)兒后即可得出分析結(jié)果。重點(diǎn)關(guān)注 “CPU consuming threads”類別下的線程俊柔,點(diǎn)擊具體某個(gè)線程進(jìn)一步定位問題代碼筹麸。

    imaged0dbd.png

    imageea94c.png
    image61a37.png
  5. 如果是內(nèi)存問題推薦使用jmap命令dump heap信息,然后使用MAT分析工具進(jìn)行分析雏婶,移步詳見此文>>物赶。

    最新MAT工具下載如果是64位,直接打開會(huì)提示“Java was started but returned exit code=13”報(bào)錯(cuò)留晚,解決方法重新安裝64位的jdk版本酵紫。 我是直接改掉對(duì)應(yīng)啟動(dòng)的jdk路徑下的javaw.exe程序,指向64位的 jdk/bin目錄下的javaw.exe倔丈。
    # 導(dǎo)出堆內(nèi)存信息命令:jmap -dump:<dump-options> <pid> jmap -dump:format=b,file=heap.bin 6 # jmap -histo:live <pid> #統(tǒng)計(jì)對(duì)象count 憨闰,live表示在使用 # jmap -histo <pid> >mem.txt #打印比較有多少個(gè)對(duì)象占了多少內(nèi)存的信息,一般重定向文件

題外話:如果是Spring Boot2.0應(yīng)用并且配置了actuator需五,配置開啟堆內(nèi)存和線程的dump接口鹉动,通過瀏覽器訪問即可獲得dump文件。

二宏邮、tomcat日志分析

以上步驟還不能定位問題原因的泽示,只能進(jìn)行應(yīng)用日志的分析。以下介紹一些使用linux命令的分析技巧蜜氨。(當(dāng)然如果已經(jīng)搭建好ELK械筛,可以通過ELK快速篩選異常時(shí)段的請(qǐng)求日志信息)

通過zabbix等監(jiān)控工具,定位應(yīng)用CPU或者內(nèi)存異常時(shí)段飒炎,日志排查以異常時(shí)段前后延長一小段時(shí)間為主埋哟。
題外話:
1.win10支持linux子系統(tǒng),不用特地為了使用linux命令裝個(gè)虛擬機(jī),詳情搜索win10 linux子系統(tǒng)安裝赤赊。

  1. 或者可以安裝git客戶端程序闯狱,利用其提供的Git Bash客戶端即可享受Linux的相關(guān)命令。
### 分析tomcat的access日志抛计,假設(shè)CPU或內(nèi)存飆升時(shí)段是2019-08-29 16:00:00 ~16:40:00之間
## 截取指定時(shí)段的日志內(nèi)容
# 1.日志時(shí)間格式為 -“2019-08-29 09:25:55606后面跟日志內(nèi)容”
sed -n '/2019-08-29 16:00:00/,/2019-08-29 16:40:00/'p localhost_access_log.2019-08-29.txt > analyse_time.log
# 2.日志時(shí)間格式為 -“22/Feb/2019:15:57:00”
sed -n '/29\/Aug\/2019:16:00:00/,/29\/Aug\/2019:16:40:00/'p  localhost_access_log.2019-08-29.txt > analyse_time.log

## 獲取指定時(shí)段QPS(升序排列,看最后幾列最大qps數(shù)據(jù)即可評(píng)判是否并發(fā)數(shù)過大)
cat analyse_time.txt|awk '{Times[$4]++}END{for(a in Times) print a,Times[a]}'| sort -nk2|column -t > analyse_qps.log

## 獲取指定時(shí)段按請(qǐng)求URL分組的QPS(帶url參數(shù))
cat analyse_time.txt|\
    awk '{gsub("\\:","_",$4);gsub("\\[","",$4);Times[$4]++;TimesURLs[$4":"$7]++}
      END{for(tturl in TimesURLs)
             {
               split(tturl,INFO,"\\:")
               printf("時(shí)間:%s 總訪問量:%d 訪問的URL:%s 訪問量:%d\n",INFO[1],Times[INFO[1]],INFO[2],TimesURLs[tturl])
             }
         }'|sort -nk2 -nrk4|column -t > analyse_qps_url_by_params.log

## 獲取指定時(shí)段按請(qǐng)求URL分組的QPS(不帶url參數(shù))
cat analyse_time.txt|\
    awk '{gsub("\\:","_",$4);gsub("\\[","",$4);split($7,UP,"\\?");Times[$4]++;TimesURLs[$4":"UP[1]]++}
      END{for(tturl in TimesURLs)
             {
               split(tturl,INFO,"\\:")
               printf("時(shí)間:%s 總訪問量:%d 訪問的URL:%s 訪問量:%d\n",INFO[1],Times[INFO[1]],INFO[2],TimesURLs[tturl])
             }
         }'|sort -nk2 -nrk4|column -t > analyse_qps_url.log

## 獲取指定時(shí)段按IP分組的訪問次數(shù)
cat analyse_time.txt|awk '{IPS[$1]++}END{for(a in IPS) print a,IPS[a]}'| sort -nk2|column -t > analyse_ip_total.log

### 通過以上access日志大致可以定位出訪問頻繁的請(qǐng)求url以及進(jìn)一步縮短定位的日志時(shí)段哄孤,根據(jù)上一步驟得到的請(qǐng)求url和時(shí)間分析具體的應(yīng)用日志
## 截取指定時(shí)段的日志內(nèi)容同上
sed -n '/2019-08-29 16:00:00/,/2019-08-29 16:40:00/'p app.info.log > analyse_info_time.log

## 假設(shè)查找到 16:40:30秒下的請(qǐng)求url"app/job/export"請(qǐng)求過于頻繁,可以通過以下定位到具體應(yīng)用日志
cat analyse_info_time.log|grep '2019-08-29 16:40:30'|grep 'app/job/export' >analyse_info_url.log

## 如果應(yīng)用日志過多吹截,比如有app.info.log~app.info.log.20 多個(gè)日志文件瘦陈,如何快速定位要查詢的內(nèi)容在哪個(gè)日志文件中?
find app.info.log.*| xargs grep -ri "SIMPLEJOB-Thread-119" -l
## 查找指定內(nèi)容并顯示前后100行
cat app.info.log|grep -C 100 "SIMPLEJOB-Thread-119"
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末波俄,一起剝皮案震驚了整個(gè)濱河市晨逝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌弟断,老刑警劉巖咏花,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異阀趴,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)苍匆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門刘急,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人浸踩,你說我怎么就攤上這事叔汁。” “怎么了检碗?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵据块,是天一觀的道長。 經(jīng)常有香客問我折剃,道長另假,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任怕犁,我火速辦了婚禮边篮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘奏甫。我一直安慰自己戈轿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布阵子。 她就那樣靜靜地躺著思杯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪挠进。 梳的紋絲不亂的頭發(fā)上色乾,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天腾么,我揣著相機(jī)與錄音,去河邊找鬼杈湾。 笑死解虱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的漆撞。 我是一名探鬼主播殴泰,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼浮驳!你這毒婦竟也來了悍汛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤至会,失蹤者是張志新(化名)和其女友劉穎离咐,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奉件,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宵蛀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了县貌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片术陶。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖煤痕,靈堂內(nèi)的尸體忽然破棺而出梧宫,到底是詐尸還是另有隱情,我是刑警寧澤摆碉,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布塘匣,位于F島的核電站,受9級(jí)特大地震影響巷帝,放射性物質(zhì)發(fā)生泄漏忌卤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一锅睛、第九天 我趴在偏房一處隱蔽的房頂上張望埠巨。 院中可真熱鬧,春花似錦现拒、人聲如沸辣垒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勋桶。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間例驹,已是汗流浹背捐韩。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鹃锈,地道東北人荤胁。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像屎债,于是被迫代替她去往敵國和親仅政。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345