首页 > 代码库 > zabbix使用zabbix_java_gateway 监控java应用进程

zabbix使用zabbix_java_gateway 监控java应用进程

JAVA-GATEWAY

Zabbix本身不支持直接监控Java,在zabbix 1.8以前,只能使用Zapcat来做代理监控,而且要修改源代码,非常麻烦。所有后来为了解决这个监控问题,Zabbix和Java双方应运生成了各自的代理监控程序:zabbix 2.0以后添加了服务进程zabbix-java-gateway;Java有了JMX,全称是Java Management Extensions,即Java管理扩展

技术分享

比如:当Zabbix-Server需要知道java应用程序的某项性能的时候,会启动自身的一个Zabbix-JavaPollers进程去连接Zabbix-JavaGateway请求数据,而ZabbixJavagateway收到请求后使用“JMXmanagementAPI”去查询特定的应用程序,而前提是应用程序这端在开启时需要“-Dcom.sun.management.jmxremote”参数来开启JMX远程查询就行。Java程序会启动自身的一个简单的小程序端口12345向Zabbix-JavaGateway提供请求数据。


开始监控部署  

从上面的原理图中我们可以看出,配置Zabbix监控Java应用程序的关键点在于:配置Zabbix-JavaGateway、让Zabbix-Server能够连接Zabbix-JavaGateway、Tomcat开启JVM远程监控功能等





网上的大多数文章都配置的是被动模式(即zabbix server 去想java进程去取数据),这样会造成zabbix server的压力过大,所以应该采用主动模式(写一个zabbix类,然后主动去上报数据)

代码如下:

zabbix.py

cat zabbix.py
#!/usr/bin/python
import os
import time
import socket
import struct
import cPickle
import logging
try:
    from hashlib import sha1
except ImportError:
    from sha import sha as sha1
try:
    import json
except ImportError:
    import simplejson as json
DUMP = ‘dump‘
if not os.path.isdir(DUMP):
    os.makedirs(DUMP, mode=0755)
class Zabbix(object):
    logger = logging.getLogger(‘zabbix‘)
    def __init__(self, values=None):
        if values is not None:
            self.__dict__[‘values‘] = values
    def __getattr__(self, name):
        if name in (‘values‘):
            return self.__dict__[name]
        return None
    def __setattr__(self, name, value):
        if name == ‘values‘:
            self.__dict__[name] = value
    def gen_request(self, jsons):
        if isinstance(jsons, basestring):
            data = ‘%s\n‘ % jsons
        else:
            data = json.dumps(jsons)
        header = ‘ZBXD\x01‘
        datalen = struct.pack(‘Q‘, len(data))
        return header + datalen + data
    def dump(self, host, port, jsons):
        data = {‘host‘: host, ‘port‘: port, ‘jsons‘: jsons}
        hash = sha1(json.dumps(data)).hexdigest()
        path = ‘%s.%s.%d.%s.error‘ % (host, port, int(time.time()), hash)
        try:
            write = open(os.path.join(DUMP, path), ‘wb‘)
            cPickle.dump(data, write, -1)
            write.close()
        except:
            self.logger.exception(‘cannot dump to file %s‘, path)
    def get_zbx_result(self, host, port, jsons):
        retry = 3
        while retry:
            try:
                data = self._get_zbx_result(host, port, jsons)
                if data is None:
                    break
                return data
            except socket.error:
                self.logger.exception(‘cannot communit with zabbix‘)
            time.sleep(5)
            retry -= 1
        self.logger.error(‘cannot send data to zabbix server‘)
        self.dump(host, port, jsons)
    def _get_zbx_result(self, host, port, jsons):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        print host,port,jsons
        sock.connect((host, port))
        sock.send(self.gen_request(jsons))
        print "send %s" % self.gen_request(jsons)
        self.logger.debug(‘sent %s‘, jsons)
        recv = sock.recv(5)
        if recv != ‘ZBXD\x01‘:
            self.logger.error(‘Invalid Response‘)
            self.dump(host, port, jsons)
            return None
        recv = sock.recv(8)
        (datalen,) = struct.unpack(‘Q‘, recv)
        data = sock.recv(datalen)
        sock.close()
        self.logger.debug(‘received %s‘, data)
        return data
    def getvalue(self):
        # shoulde be {host: {key: value}}
        return self.values
    def run(self):
        hostvalues = self.getvalue()
        if not isinstance(hostvalues, dict):
            self.logger.error(‘invalid hostvalues: %s‘, str(hostvalues))
            return False
        clock = int(time.time())
        jsons = {
            ‘request‘: ‘agent data‘,
            ‘data‘: [],
            ‘clock‘: clock,
        }
        data = jsons[‘data‘]
        for host, values in hostvalues.iteritems():
            for key, value in values.iteritems():
                data.append({
                    ‘host‘: host,
                    ‘key‘: key,
                    ‘value‘: value,
                    ‘clock‘: clock,
                })
        return self.get_zbx_result(ZBX_HOST, ZBX_PORT, jsons)
    def getjmx(self, host, port, keys):
        jsons = {
            ‘request‘: ‘java gateway jmx‘,
            ‘conn‘: host,
            ‘port‘: port,
            ‘keys‘: keys,
        }
        return self.get_zbx_result(JMX_HOST, JMX_PORT, jsons)
ZBX_HOST = ‘zabbix.server.com‘
ZBX_PORT = 10051
JMX_HOST = ‘localhost‘
JMX_PORT = 10052
handler = logging.FileHandler(filename=‘/tmp/zabbix.%s.log‘ % time.strftime(‘%Y%m%d‘), mode=‘a‘)
formatter = logging.Formatter(‘%(asctime)s %(name)s %(lineno)s %(levelname)s %(message)s‘)
handler.setFormatter(formatter)
logger = logging.getLogger()
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
if __name__ == ‘__main__‘:
    zbx = Zabbix()
    print zbx.getjmx(‘localhost‘, 8081, [‘jmx["Standalone:type=Manager,path=/,host=localhost",activeSessions]‘, ‘jmx["java.lang:type=Runtime",Uptime]‘, ‘jmx["Catalina:type=GlobalRequestProcessor,name=\\"http-bio-8080\\"",bytesSent]‘])
    pass



cat zabbix_wiki_node1_java.py   

#!/usr/bin/env python
#fileencoding: utf-8
ITEMS = [
‘jmx["java.lang:type=ClassLoading",LoadedClassCount]‘,
‘jmx["java.lang:type=ClassLoading",TotalLoadedClassCount]‘,
‘jmx["java.lang:type=ClassLoading",UnloadedClassCount]‘,
‘jmx["java.lang:type=Memory",HeapMemoryUsage.committed]‘,
‘jmx["java.lang:type=Memory",HeapMemoryUsage.max]‘,
‘jmx["java.lang:type=Memory",HeapMemoryUsage.used]‘,
‘jmx["java.lang:type=Memory",NonHeapMemoryUsage.committed]‘,
‘jmx["java.lang:type=Memory",NonHeapMemoryUsage.max]‘,
‘jmx["java.lang:type=Memory",NonHeapMemoryUsage.used]‘,
‘jmx["java.lang:type=MemoryPool,name=Code Cache",Usage.committed]‘,
‘jmx["java.lang:type=MemoryPool,name=Code Cache",Usage.max]‘,
‘jmx["java.lang:type=MemoryPool,name=Code Cache",Usage.used]‘,
‘jmx["java.lang:type=MemoryPool,name=PS Eden Space",Usage.committed]‘,
‘jmx["java.lang:type=MemoryPool,name=PS Eden Space",Usage.max]‘,
‘jmx["java.lang:type=MemoryPool,name=PS Eden Space",Usage.used]‘,
‘jmx["java.lang:type=MemoryPool,name=PS Old Gen",Usage.committed]‘,
‘jmx["java.lang:type=MemoryPool,name=PS Old Gen",Usage.max]‘,
‘jmx["java.lang:type=MemoryPool,name=PS Old Gen",Usage.used]‘,
‘jmx["java.lang:type=MemoryPool,name=PS Perm Gen",Usage.committed]‘,
‘jmx["java.lang:type=MemoryPool,name=PS Perm Gen",Usage.max]‘,
‘jmx["java.lang:type=MemoryPool,name=PS Perm Gen",Usage.used]‘,
‘jmx["java.lang:type=MemoryPool,name=PS Survivor Space",Usage.committed]‘,
‘jmx["java.lang:type=MemoryPool,name=PS Survivor Space",Usage.max]‘,
‘jmx["java.lang:type=MemoryPool,name=PS Survivor Space",Usage.used]‘,
‘jmx["java.lang:type=OperatingSystem",MaxFileDescriptorCount]‘,
‘jmx["java.lang:type=OperatingSystem",OpenFileDescriptorCount]‘,
‘jmx["java.lang:type=Runtime",Uptime]‘,
‘jmx["java.lang:type=Threading",DaemonThreadCount]‘,
‘jmx["java.lang:type=Threading",PeakThreadCount]‘,
‘jmx["java.lang:type=Threading",ThreadCount]‘,
‘jmx["java.lang:type=Threading",TotalStartedThreadCount]‘,
‘jmx["Standalone:type=GlobalRequestProcessor,name=http-8090",bytesReceived]‘,
‘jmx["Standalone:type=GlobalRequestProcessor,name=http-8090",bytesSent]‘,
‘jmx["Standalone:type=GlobalRequestProcessor,name=http-8090",errorCount]‘,
‘jmx["Standalone:type=GlobalRequestProcessor,name=http-8090",processingTime]‘,
‘jmx["Standalone:type=GlobalRequestProcessor,name=http-8090",requestCount]‘,
‘jmx["Standalone:type=Manager,path=/,host=localhost",activeSessions]‘,
‘jmx["Standalone:type=Manager,path=/,host=localhost",maxActiveSessions]‘,
‘jmx["Standalone:type=Manager,path=/,host=localhost",maxActive]‘,
‘jmx["Standalone:type=Manager,path=/,host=localhost",rejectedSessions]‘,
‘jmx["Standalone:type=Manager,path=/,host=localhost",sessionCounter]‘,
‘jmx["Standalone:type=ProtocolHandler,port=8090",compression]‘,
‘jmx["Standalone:type=ThreadPool,name=http-8090",currentThreadCount]‘,
‘jmx["Standalone:type=ThreadPool,name=http-8090",currentThreadsBusy]‘,
‘jmx["Standalone:type=ThreadPool,name=http-8090",maxThreads]‘,
]
from zabbix import Zabbix
from zabbix import json
def getjmxkey(key):
    # key = key.replace(‘http-8080‘, ‘\\"http-bio-8080\\"‘)
    # key = key.replace(‘path=/‘, ‘context=/‘)
    return key
def getjmxvalue(value):
    if isinstance(value, dict):
        return value.get(‘value‘, u‘‘).encode(‘utf8‘)
    return ‘‘
if __name__ == ‘__main__‘:
    host = ‘it-tw01‘
    zbx = Zabbix()
    jmxkeys = [getjmxkey(x) for x in ITEMS]
    data = zbx.getjmx(‘it-tw01‘, ‘8410‘, jmxkeys)
    try:
        results = json.loads(data)
    except:
        results = {}
    if isinstance(results, dict) and results[‘response‘] == ‘success‘:
        jmxvalues = [getjmxvalue(x) for x in results.get(‘data‘, [])]
        hostvalues = {host: dict(zip(ITEMS, jmxvalues))}
        Zabbix(hostvalues).run()
# vim: set sta sw=4 et:


crontab

* * * * * /home/sankuai/monitor/zabbix_wiki_node1_java.py


zabbix

/etc/zabbix# ls

zabbix_agentd.conf  zabbix_agentd.confn-place  zabbix_agentd.d  zabbix_java_gateway.conf


it-tw01需要关联的模板见附件




特别注意:

编译安装zabbix server需要加上--enable-java以支持jmx监控,如果之前的zabbix server没加,那么请重新编译安装,参考编译参数

安装软件

yum install -y java java-devel zabbix-java-gateway

更多的请参考这个文章:http://www.iyunv.com/thread-269939-1-1.html


zabbix使用zabbix_java_gateway 监控java应用进程