roger2001c 发表于 2019-1-19 06:01:04

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管理扩展
  http://s5.运维网.com/wyfs02/M01/8A/FC/wKioL1hA8FKiTpeWAABu7oWbNfE824.png
  比如:当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__
      return None
    def __setattr__(self, name, value):
      if name == 'values':
            self.__dict__ = 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 =
    data = zbx.getjmx('it-tw01', '8410', jmxkeys)
    try:
      results = json.loads(data)
    except:
      results = {}
    if isinstance(results, dict) and results['response'] == 'success':
      jmxvalues = )]
      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.confzabbix_agentd.confn-placezabbix_agentd.dzabbix_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
  



附件:http://down.运维网.com/data/2368443

页: [1]
查看完整版本: zabbix使用zabbix_java_gateway 监控java应用进程