Zabbix监控JVM(微服务进程)_zabbix java 微服务

# java -version
java version "1.8.0_161"
Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)

关于微服务的信息主要通过jstat获取,如下

# ps -ef|grep java
root     28131     1  0 11:17 ?        00:00:56 java -Xms100M -Xmx500M -Xmn150M -jar /data/work/service_jar/manageMiddle.jar --server.port=20000 --management.port=20001 --config.profile=test
root     28305     1  0 11:26 ?        00:00:51 java -Xms100M -Xmx300M -Xmn100M -jar /data/work/service_jar/resourceService.jar --server.port=18000 --management.port=18001 --config.profile=test
root     29067     1  0 11:59 ?        00:00:54 java -Xms100M -Xmx500M -Xmn150M -jar /data/work/service_jar/systemService.jar --server.port=21000 --management.port=21001 --config.profile=test
root     31345 29980  0 14:03 pts/0    00:00:00 grep --color=auto java
# jstat -gcutil 28131
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT   
 67.75   0.00  74.28  81.92  97.29  94.90     74    1.248     7    1.065    2.313
# jstat -gc 28131
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
14336.0 14848.0 9712.2  0.0   122880.0 91488.9   55808.0    45716.6   56704.0 55169.1 7296.0 6924.1     74    1.248   7      1.065    2.313

关于输出结果的参数解释

S0C:年轻代中第一个survivor(幸存区)的容量 (字节)
S1C:年轻代中第二个survivor(幸存区)的容量 (字节)
S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
EC:年轻代中Eden(伊甸园)的容量 (字节)
EU:年轻代中Eden(伊甸园)目前已使用空间 (字节)
OC:Old代的容量 (字节)
OU:Old代目前已使用空间 (字节)
PC:Perm(持久代)的容量 (字节)
PU:Perm(持久代)目前已使用空间 (字节)
YGC:从应用程序启动到采样时年轻代中gc次数
YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)
FGC:从应用程序启动到采样时old代(全gc)gc次数
FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT:从应用程序启动到采样时gc用的总时间(s)

NGCMN:年轻代(young)中初始化(最小)的大小 (字节)

NGCMX:年轻代(young)的最大容量 (字节)

NGC:年轻代(young)中当前的容量 (字节)

OGCMN:old代中初始化(最小)的大小 (字节)

OGCMX:old代的最大容量 (字节)

OGC:old代当前新生成的容量 (字节)

PGCMN:perm代中初始化(最小)的大小 (字节)

PGCMX:perm代的最大容量 (字节)

PGC:perm代当前新生成的容量 (字节)

S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比

S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比

E:年轻代中Eden(伊甸园)已使用的占当前容量百分比

O:old代已使用的占当前容量百分比

P:perm代已使用的占当前容量百分比

S0CMX:年轻代中第一个survivor(幸存区)的最大容量 (字节)

S1CMX :年轻代中第二个survivor(幸存区)的最大容量 (字节)

ECMX:年轻代中Eden(伊甸园)的最大容量 (字节)

DSS:当前需要survivor(幸存区)的容量 (字节)(Eden区已满)

TT: 持有次数限制

MTT : 最大持有次数限制

Jdk1.8中取消了永久区Perm

4、监控脚本

微服务全部放置在固定的目录内,自动发现微服务脚本为

# cat java_discovery.py 
#/usr/bin/python
#This script is used to discovery disk on the server
import subprocess
import os
import socket
import json
import glob
  
java_names_file='java_names.txt'
javas=[]
if os.path.isfile(java_names_file):
#   print 'java_names_file exists!'
#####
##### here should use % (java_names_file) instead of using the python variable java_names_file directly inside the '''   ''' quotes
#####
  
   args='''awk -F':' '{print $1':'$2}' %s'''  % (java_names_file)
   t=subprocess.Popen(args,shell=True,stdout=subprocess.PIPE).communicate()[0]
#elif glob.glob('/opt/xx/*_tomcat') and not os.path.isdir('/opt/logs/logstash') and not os.path.isdir('/opt/app/elasticsearch/config'):
elif glob.glob('/data/work/service_jar/*.jar'): 
  t=subprocess.Popen('cd /data/work/service_jar && ls *.jar|grep jar',shell=True,stdout=subprocess.PIPE)
   
for java in t.stdout.readlines():
    if len(java) != 0:
       javas.append({'{#JAVA_NAME}':java.strip('\n').strip(':')})
print json.dumps({'data':javas},indent=4,separators=(',',':'))

脚本内的目录可以自由修改

输出结果为json格式

# python java_discovery.py 
{
    "data":[
        {
            "{#JAVA_NAME}":"insuranceService.jar"
        },
        {
            "{#JAVA_NAME}":"manageMiddle.jar"
        },
        {
            "{#JAVA_NAME}":"resourceService.jar"
        },
        {
            "{#JAVA_NAME}":"systemService.jar"
        }
    ]
}

对微服务进行信息获取,并利用zabbix_sender发送的脚本为

# cat jstat_status.py
#!/usr/bin/python
  
import subprocess
import sys
import os
  
__maintainer__ = "Francis"
  
jps = '/data/jdk1.8/bin/jps'
jstat = '/data/jdk1.8/bin/jstat'
zabbix_sender = "/usr/bin/zabbix_sender"
zabbix_conf = "/etc/zabbix/zabbix_agentd.conf"      
send_to_zabbix = 1
ip=os.popen("ifconfig|grep 'inet '|grep -v '127.0'|xargs|awk -F '[ :]' '{print $3}'").readline().rstrip()
serverip="172.19.138.53"
  
#"{#JAVA_NAME}":"tomcat_web_1"
  
  
def usage():
    """Display program usage"""
  
    print "\nUsage : ", sys.argv[0], " java_name alive|all"
    print "Modes : \n\talive : Return pid of running processs\n\tall : Send jstat stats as well"
    sys.exit(1)
  
  
class Jprocess:
  
    def __init__(self, arg):
        self.pdict = {
        "jpname": arg,
        }
  
        self.zdict = {
        "Heap_used" : 0,
                "Heap_ratio" : 0,
        "Heap_max" : 0,
        "Perm_used" : 0,
                "Perm_ratio" : 0,
        "Perm_max"  : 0,
                "S0_used"   : 0,
                "S0_ratio"  : 0,
                "S0_max"    : 0,
                "S1_used"   : 0,
                "S1_ratio"  : 0,
                "S1_max"    : 0,
                "Eden_used" : 0,
                "Eden_ratio" : 0,
                "Eden_max"  : 0,
                "Old_used"  : 0,
                "Old_ratio" : 0,
                "Old_max"   : 0,
                "YGC"       : 0,
                "YGCT"      : 0,
                "YGCT_avg"      : 0,
                "FGC"       : 0,
                "FGCT"      : 0,
                "FGCT_avg"      : 0,
                "GCT"       : 0,
                "GCT_avg"       : 0,
                  
        }
  
  
    def chk_proc(self):
#  ps -ef|grep java|grep tomcat_web_1|awk '{print $2}'
#                print self.pdict['jpname']
                pidarg = '''ps -ef|grep java|grep %s|grep -v grep | grep -v jstat_status.py |awk '{print $2}' ''' %(self.pdict['jpname']) 
                #pidout = subprocess.Popen(pidarg,shell=True,stdout=subprocess.PIPE) 
                #pid = pidout.stdout.readline().strip('\n') 
                pid = subprocess.check_output(pidarg, shell=True).strip()
                if pid != "" :
                   self.pdict['pid'] = pid
#                   print "Process found :", java_name, "with pid :", self.pdict['pid']
                else:
                   self.pdict['pid'] = ""
#                   print "Process not found"
                return self.pdict['pid']
  
    def get_jstats(self):
        if self.pdict['pid'] == "":
            return False
        self.pdict.update(self.fill_jstats("-gc"))
        self.pdict.update(self.fill_jstats("-gccapacity"))
        self.pdict.update(self.fill_jstats("-gcutil"))
  
#        print "\nDumping collected stat dictionary\n-----\n", self.pdict, "\n-----\n"
  
    def fill_jstats(self, opts):
#        print "\nGetting", opts, "stats for process", self.pdict['pid'], "with command : sudo", jstat, opts, self.pdict['pid'] ,"\n"
#        jstatout = subprocess.Popen(['sudo','-u','tomcat', jstat, opts, self.pdict['pid']], stdout=subprocess.PIPE)
        #print([jstat, opts, self.pdict['pid']])
        jstatout = subprocess.Popen([jstat, opts, self.pdict['pid']], stdout=subprocess.PIPE)
        stdout, stderr = jstatout.communicate()
        legend, data = stdout.split('\n',1)
        mydict = dict(zip(legend.split(), data.split()))
        return mydict
  
    def compute_jstats(self):
        if self.pdict['pid'] == "":
            return False
        self.zdict['S0_used'] = format(float(self.pdict['S0U']) * 1024,'0.2f')
        self.zdict['S0_max'] =  format(float(self.pdict['S0C']) * 1024,'0.2f')
        self.zdict['S0_ratio'] = format(float(self.pdict['S0']),'0.2f')
 
        self.zdict['S1_used'] = format(float(self.pdict['S1U']) * 1024,'0.2f')
        self.zdict['S1_max'] = format(float(self.pdict['S1C']) * 1024,'0.2f')
        self.zdict['S1_ratio'] = format(float(self.pdict['S1']),'0.2f')
  
        self.zdict['Old_used'] = format(float(self.pdict['OU']) * 1024,'0.2f')
        self.zdict['Old_max'] =  format(float(self.pdict['OC']) * 1024,'0.2f')
        self.zdict['Old_ratio'] = format(float(self.pdict['O']),'0.2f')
 
        self.zdict['Eden_used'] = format(float(self.pdict['EU']) * 1024,'0.2f')
        self.zdict['Eden_max'] = format(float(self.pdict['EC']) * 1024,'0.2f')
        self.zdict['Eden_ratio'] = format(float(self.pdict['E']),'0.2f')            
# self.zdict['Perm_used'] = format(float(self.pdict['PU']) * 1024,'0.2f')
# self.zdict['Perm_max'] = format(float(self.pdict['PC']) * 1024,'0.2f')
# self.zdict['Perm_ratio'] = format(float(self.pdict['P']),'0.2f')
                 
        self.zdict['Heap_used'] = format((float(self.pdict['EU']) + float(self.pdict['S0U']) + float(self.pdict['S1U'])  + float(self.pdict['OU'])) * 1024,'0.2f')
        self.zdict['Heap_max'] = format((float(self.pdict['EC']) + float(self.pdict['S0C']) + float(self.pdict['S1C'])  + float(self.pdict['OC'])) * 1024,'0.2f')
        self.zdict['Heap_ratio'] = format(float(self.zdict['Heap_used']) / float(self.zdict['Heap_max'])*100,'0.2f')
 
        self.zdict['YGC'] = self.pdict['YGC']
        self.zdict['FGC'] = self.pdict['FGC']
        self.zdict['YGCT'] = format(float(self.pdict['YGCT']),'0.3f')
        self.zdict['FGCT'] = format(float(self.pdict['FGCT']),'0.3f')
        self.zdict['GCT'] = format(float(self.pdict['GCT']),'0.3f') 
     
        if self.pdict['YGC'] == '0':
           self.zdict['YGCT_avg'] = '0'
        else: 
           self.zdict['YGCT_avg'] = format(float(self.pdict['YGCT'])/float(self.pdict['YGC']),'0.3f')
        if self.pdict['FGC'] == '0':
           self.zdict['FGCT_avg'] = '0'
        else:
           self.zdict['FGCT_avg'] = format(float(self.pdict['FGCT'])/float(self.pdict['FGC']),'0.3f')
        if self.pdict['YGC'] == '0' and self.pdict['FGC'] == '0':
           self.zdict['GCT_avg'] = '0' 
        else:
           self.zdict['GCT_avg'] = format(float(self.pdict['GCT'])/(float(self.pdict['YGC']) + float(self.pdict['FGC'])),'0.3f') 
                   
  
       # print "Dumping zabbix stat dictionary\n-----\n", self.zdict, "\n-----\n"
  
    def send_to_zabbix(self, metric):
####      {#JAVA_NAME} tomcat_web_1 
####      UserParameter=java.discovery,/usr/bin/python /opt/app/zabbix/sbin/java_discovery.py
####      UserParameter=java.discovery_status[*],/opt/app/zabbix/sbin/jstat_status.sh $1 $2 $3 $4 
####      java.discovery_status[tomcat_web_1,Perm_used]
####      java.discovery_status[{#JAVA_NAME},Perm_used]
        key = "java.discovery_status[" + self.pdict['jpname'] + "," + metric + "]"
  
        if self.pdict['pid'] != "" and  send_to_zabbix > 0:
           #print key + ":" + str(self.zdict[metric])
           try:
                                       
                 subprocess.call([zabbix_sender, "-c", zabbix_conf, "-k", key, "-o", str(self.zdict[metric])], stdout=FNULL,stderr=FNULL, shell=False) 
           except OSError, detail:
                 print "Something went wrong while exectuting zabbix_sender : ", detail
        else:
           print "Simulation: the following command would be execucted :\n", zabbix_sender, "-c", zabbix_conf, "-k", key, "-o", self.zdict[metric], "\n"
  
  
accepted_modes = ['alive', 'all']
  
 
if len(sys.argv) == 3 and sys.argv[2] in accepted_modes:
    java_name = sys.argv[1]
    mode = sys.argv[2]
else:
    usage()
  
  
#Check if process is running / Get PID
jproc = Jprocess(java_name) 
pid = jproc.chk_proc()
  
  
if pid != "" and  mode == 'all':
   jproc.get_jstats()
   #print jproc.zdict
   jproc.compute_jstats()               
   FNULL = open(os.devnull, 'w')
   for key in jproc.zdict:
       #print key,jproc.zdict[key]
       jproc.send_to_zabbix(key)
   FNULL.close()
  # print pid
 
  


![img](https://img-blog.csdnimg.cn/img_convert/6dde1c23a5f71a707a729a224f1c793b.png)
![img](https://img-blog.csdnimg.cn/img_convert/ad828b5e321d48499f5ce68d6e883d75.png)
![img](https://img-blog.csdnimg.cn/img_convert/065a5ca5cae1d66b764f53878a767d86.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!**

_jstats()               
   FNULL = open(os.devnull, 'w')
   for key in jproc.zdict:
       #print key,jproc.zdict[key]
       jproc.send_to_zabbix(key)
   FNULL.close()
  # print pid
 
  


[外链图片转存中...(img-XAPb9eC4-1719242683204)]
[外链图片转存中...(img-JCQTwqdJ-1719242683205)]
[外链图片转存中...(img-89JFIDsi-1719242683206)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值