java根据负载自动抓取jstack dump详情

 更新时间:2022年09月27日 15:03:59   作者:sdmei  
这篇文章主要介绍了java根据负载自动抓取jstack dump详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下

java应用CPU有波动,事后怎么分析?

目前我采用的方案是根据CPU负载自动执行jstack,并将文件上传到OSS。

 环境:阿里云 + k8s + springcloud + prometheus + oss

容器镜像安装python 2.7

涉及以下几个文件:

oss相关的文件包括:oss客户端和配置文件;

逻辑主要在脚本:mon_cpu_jstack.py 

  • 两个参数:CPU阈值,profile环境(prod \ test等)
  • 每10s 执行一次脚本(跳过起初的3分钟,因为应用启动时CPU负载高是正常的);
  • 通过top获取CPU,超过阈值则执行jstack;
  • 如果CPU消耗最大进程是GC,拉取jmap信息;
  • 每小时最大执行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调用上述python脚本(profile直接从环境变量中获取)

# 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调用脚本自动执行:

 最终生成的oss文件:

第一层目录:profiles

第二层目录:应用名称

第三层目录:具体jstack文件

文件名最后的数字是当时的CPU使用量,如166指1.66C

到此这篇关于java根据负载自动抓取jstack dump详情的文章就介绍到这了,更多相关java抓取jstack dump内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MybatisPlus字段类型转换的实现示例

    MybatisPlus字段类型转换的实现示例

    本文主要介绍了MybatisPlus如何完成字段类型转换,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • 玩转spring boot 快速开始(1)

    玩转spring boot 快速开始(1)

    玩转spring boot,快速开始spring boot学习,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • JAVA中使用FileWriter写数据到文本文件步骤详解

    JAVA中使用FileWriter写数据到文本文件步骤详解

    这篇文章主要介绍了JAVA中使用FileWriter写数据到文本文件步骤详解,FileWriter类提供了多种写入字符的方法,包括写入单个字符、写入字符数组和写入字符串等,它还提供了一些其他的方法,如刷新缓冲区、关闭文件等,需要的朋友可以参考下
    2023-10-10
  • SpringMVC打印请求参数和响应数据最优方案

    SpringMVC打印请求参数和响应数据最优方案

    项目中经常需要打印http请求的参数和响应数据,本文给大家讲解如何在SpringMVC打印请求参数和响应数据最优方案,感兴趣的朋友跟随小编一起看看吧
    2023-07-07
  • Mybatis之foreach标签内传入list为空的问题

    Mybatis之foreach标签内传入list为空的问题

    这篇文章主要介绍了Mybatis之foreach标签内传入list为空的问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • SpringMVC中的DispatcherServlet详细解析

    SpringMVC中的DispatcherServlet详细解析

    这篇文章主要介绍了SpringMVC中的DispatcherServlet详细解析,DispatcherServlet也是一个Servlet,它也能通过Servlet的API来响应请求,从而成为一个前端控制器,Web容器会调用Servlet的doGet()以及doPost()等方法,需要的朋友可以参考下
    2023-12-12
  • springboot枚举类型传递的步骤

    springboot枚举类型传递的步骤

    这篇文章主要介绍了springboot枚举类型传递的步骤,帮助大家更好的理解和学习使用springboot,感兴趣的朋友可以了解下
    2021-04-04
  • 网络爬虫案例解析

    网络爬虫案例解析

    本文主要介绍了网络爬虫的小案例。具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03
  • mybatis不加@Parm注解报错的解决方案

    mybatis不加@Parm注解报错的解决方案

    这篇文章主要介绍了mybatis不加@Parm注解报错的解决方案,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • Java的Struts框架中<results>标签的使用方法

    Java的Struts框架中<results>标签的使用方法

    这篇文章主要介绍了Java的Struts框架中<results>标签的使用方法,Struts框架是Java的SSH三大web开发框架之一,需要的朋友可以参考下
    2015-11-11

最新评论