zoukankan      html  css  js  c++  java
  • 在k8s中导出jvm内存错误dump文件到OSS

    现状

    加参数 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=logs/test.dump 可以实现在jvm发生内存错误后 会生成dump文件 方便开发人员分析异常原因。

    当运行在k8s中,如果进程发生错误 导出dump文件后 ,k8s会重启dokcer容器,上一次崩溃生成的dump文件就没有了。如果应用并没有完全崩溃 此时极其不稳定 最好也能通知到技术人员来处理。这样不方便我们排查原因 所有写了一个小工具。大概原理如下

    1、 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=logs/test.dump 当发生内存错误的时候 导出堆文件
    2、 -XX:OnOutOfMemoryError=./dumpError.sh 当发生内存溢出的时候,让JVM调用一个shell脚本 这个shell脚本可以做一些资源整理操作 比如kill掉当前进程并重启

    依赖上面2点jvm特性 就能做到把dump文件收集起来 是通知技术人员也好(比如发送订单、短信报警等)、然后再把dump文件上传到OSS 或者其他的文件存储中。 需要值得注意的是-XX:OnOutOfMemoryError=xx.sh 执行的脚本不能传脚本参数,所以尽可能把参数都封装在另一个脚本中。

    方案实现

    基于Go简单的写了一个上传阿里OSS的方法 这里用其他任何语言都可以的,至于用GO的原因很简单,有第三方库可以调用、运行的机器上也不用安装sdk、比较轻量。
    大致逻辑如下

    jvmdump.go

    init获取程序的输入参数

    func init(){
    	fmt.Println("init....")
    	flag.StringVar(&env, "env", "test", "test") //用于区分环境 
    	flag.StringVar(&ddtoken, "ddtoken", "", "ddtoken") //用于报警用的 钉钉机器人TOKEN
    	flag.StringVar(&dumpFile, "dfile", "", "dfile") // dump文件的地址
    	flag.StringVar(&pod, "pod", "", "pod") //k8s中的pod  只是记录一下 方便排查 
    }
    
    

    main函数逻辑

    
    func main() {
    	fmt.Println("start invoke dump...")
    	flag.Parse() //解析输入参数
    	fmt.Printf("dumpFile %s ,env %s token %s\n",dumpFile,env,ddtoken)
    	exist, err := FileExists(dumpFile) //验证dump文件是否存在 只有存在的时候才去处理收集dump文件逻辑
    	if err != nil {
    		fmt.Printf("验证文件是否存在发生错误![%v]\n", err)
    		return
    	}
    	if exist {
    		//https://help.aliyun.com/document_detail/88604.html
    		var url=uploadOSS(dumpFile) //上传阿里oss
    		fmt.Printf("OSS上传完成 %s\n", url)
    		if enabledd{
    		//钉钉群机器人发送工具 https://github.com/braumye/grobot 
    			notifyDD(url) //通知钉钉群机器人
    		}
    	}else{
    		fmt.Printf("dump文件不存在 %s\n",dumpFile)
    	}
    }
    
    

    构建可执行文件

    
      set GOOS=linux
      go build -ldflags "-w -s"
    
    

    测试 验证go脚本是否正确

      echo "ffff">/opt/ttt.dump
     ./jvmdump -env test -dfile /opt/ttt.dump
    

    如果能成功上传 就可以集成到jvm上跑了,不能成功上传的话 就需要调一下go了。

    另外分享一个-XX:OnOutOfMemoryError=./dumpError.sh 参考。

    有这个shell的原因是因为 由于jvmOnOutOfMemoryError目前没有找到可以传递脚本参数的方法。 所有不能调用./jvmdump文件 故包装一下,把参数都封装在dempError.sh中 ,把所有生成的dump文件 后缀命名都设置为.dump,主要是为了方便查找。放在一个独立的目录也是可以的。

    dumpError.sh

    #!/bin/bash
    
    #循环目录
    traverse_dir()
    {
        filepath=$1
    
        for file in `ls -a $filepath`
        do
            if [ -d ${filepath}/$file ]
            then
                if [[ $file != '.' && $file != '..' ]]
                then
                    #递归
                    traverse_dir ${filepath}/$file
                fi
            else
                #调用查找指定后缀文件
                check_suffix ${filepath}/$file
            fi
        done
    	#看需要 可以kill掉进程,避免jvm没有完全崩溃 k8s不会重启pod的情况 造成应用假死问题。
    }
    
    #查找指定后缀的文件 这里在k8s环境里一般只会有一个dump文件,如果可能存在多个的dump文件文件的情况 可能需要变更一下逻辑
    check_suffix()
    {
        file=$1
    
    	#如果找到dump就调用go写的jvmdump脚本 
        if [ "${file##*.}"x = "dump"x ];then
            lib/jvmdump -e test -dfile $file -pod $HOSTNAME -ddtoken xxx
        fi
    }
    traverse_dir /opt/logs
    
    

    完整代码参考

    https://github.com/peachyy/jvmdump4k8s.git

    转载请注明出处。

    作者:peachyy

    出处:http://www.cnblogs.com/peachyy/

  • 相关阅读:
    poj 2187 Beauty Contest(旋转卡壳)
    poj 2540 Hotter Colder(极角计算半平面交)
    poj 1279 Art Gallery(利用极角计算半平面交)
    poj 3384 Feng Shui(半平面交的联机算法)
    poj 1151 Atlantis(矩形面积并)
    zoj 1659 Mobile Phone Coverage(矩形面积并)
    uva 10213 How Many Pieces of Land (欧拉公式计算多面体)
    uva 190 Circle Through Three Points(三点求外心)
    zoj 1280 Intersecting Lines(两直线交点)
    poj 1041 John's trip(欧拉回路)
  • 原文地址:https://www.cnblogs.com/peachyy/p/15539217.html
Copyright © 2011-2022 走看看