java根據(jù)負(fù)載自動抓取jstack?dump詳情
java應(yīng)用CPU有波動,事后怎么分析?
目前我采用的方案是根據(jù)CPU負(fù)載自動執(zhí)行jstack,并將文件上傳到OSS。
環(huán)境:阿里云 + k8s + springcloud + prometheus + oss
容器鏡像安裝python 2.7
涉及以下幾個文件:
oss相關(guān)的文件包括:oss客戶端和配置文件;
邏輯主要在腳本:mon_cpu_jstack.py
- 兩個參數(shù):CPU閾值,profile環(huán)境(prod \ test等)
- 每10s 執(zhí)行一次腳本(跳過起初的3分鐘,因?yàn)閼?yīng)用啟動時CPU負(fù)載高是正常的);
- 通過top獲取CPU,超過閾值則執(zhí)行jstack;
- 如果CPU消耗最大進(jìn)程是GC,拉取jmap信息;
- 每小時最大執(zhí)行3次jstack(太多無意義);
- 生成文件后通過oss客戶端上傳OSS;
# more mon_cpu_jstack.py # -*- coding: utf-8 -*- import time import commands as cm import os,sys from signal import signal, SIGPIPE, SIG_DFL signal(SIGPIPE,SIG_DFL) if len(sys.argv) != 3: print 'Usage: ' + sys.argv[0] + ' [cpu_threshold] [profiles]' sys.exit(1) cpu_th = float(sys.argv[1]) profiles = sys.argv[2] base_dir = '/opt/perf' time_list = [] def oss_upload(app_name,logfile): comm_upload = base_dir + '/ossutil64 -c ' + base_dir + '/ossutilconfig cp ' + logfile + ' oss://k8s-jstack-log/' + profiles + '/' + app_name + '/' comm_delete = 'rm -f ' + logfile os.system(comm_upload) time.sleep(1) os.system(comm_delete) def mon_and_catch(): global time_list # up to 3 times hourly if len(time_list) == 3: if time.time() - time_list[-1] <= 3600: return host_name = cm.getoutput('hostname') java_pid = cm.getoutput('top -b -n1 | grep java|awk \'{printf $1}\'') if (java_pid == ''): print 'no java_pid' return cpu_pct_str = cm.getoutput('top -b -p ' + java_pid + ' -n1 | tail -1 |awk \'{printf $9}\'') cpu_pct = float(cpu_pct_str) time_str = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime()) log_name = base_dir + '/' + host_name + '_' + time_str + '_cpu_' + cpu_pct_str.split('.')[0] + '.log' if(cpu_pct > cpu_th): time_list.insert(0, time.time()) time_list = time_list[:3] os.system('top -Hbp' + java_pid + ' -n1 >> ' + log_name) os.system('echo >> ' + log_name) os.system('jstack -l ' + java_pid + ' >> '+log_name) # if cpu is used by gc, exec jmap top_thread_id = cm.getoutput('cat ' + log_name + ' | grep java | head -1 | awk \'{print $1}\'') top_thread_id_hex = "0x" + cm.getoutput('printf \'%x\n\' ' + top_thread_id) + " " top_thread_gc = cm.getoutput('cat ' + log_name + ' | grep "' + top_thread_id_hex + '" | grep "GC" | wc -l') if top_thread_gc == '1': os.system('echo >> ' + log_name) os.system('jmap -histo:live ' + java_pid + ' | head -100 >> ' + log_name) # get app_name from hostname hostname_list = host_name.split('-') app_name_list = hostname_list[:len(hostname_list)-2] app_name='-'.join(app_name_list) if app_name[-1] in ['1','2']: app_name = app_name[:len(app_name)-1] oss_upload(app_name, log_name) if __name__ == '__main__': i = 0 while (True): # skip at startup if i > 18: mon_and_catch() time.sleep(10) i = i + 1
poststart.sh調(diào)用上述python腳本(profile直接從環(huán)境變量中獲取)
# more poststart.sh cpu_th=$1 nohup python -u /opt/perf/mon_cpu_jstack.py ${cpu_th} ${spring_profiles_active} > /opt/perf/poststart.log 2>&1 & exit 0
通過postStart調(diào)用腳本自動執(zhí)行:
最終生成的oss文件:
第一層目錄:profiles
第二層目錄:應(yīng)用名稱
第三層目錄:具體jstack文件
文件名最后的數(shù)字是當(dāng)時的CPU使用量,如166指1.66C
到此這篇關(guān)于java根據(jù)負(fù)載自動抓取jstack dump詳情的文章就介紹到這了,更多相關(guān)java抓取jstack dump內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java判斷范圍型的數(shù)據(jù)是否存在重疊的方法
遇到了個問題,同一天可以輸入多個時間段,但是每個時間段的時間不能出現(xiàn)重疊,這不就是判斷數(shù)據(jù)返回是否有重疊的變種嗎,所以本文給大家介紹了Java判斷范圍型的數(shù)據(jù)是否存在重疊的方法,需要的朋友可以參考下2024-07-07Java編程中實(shí)現(xiàn)Condition控制線程通信
這篇文章主要介紹了Java編程中實(shí)現(xiàn)Condition控制線程通信,簡單介紹了Java中控制線程通信的方法,以及對condition的解析和實(shí)例,具有一定參考價值,需要的朋友可以了解下。2017-11-11java 進(jìn)程是如何在Linux服務(wù)器上進(jìn)行內(nèi)存分配的
這篇文章主要介紹了java 進(jìn)程是如何在Linux服務(wù)器上進(jìn)行內(nèi)存分配的,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2020-11-11vue+springboot+shiro+jwt實(shí)現(xiàn)登錄功能
這篇文章主要介紹了vue+springboot+shiro+jwt實(shí)現(xiàn)登錄功能,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-04-04