通过Nagios监控Tomcat服务
1.前言
本文主要介绍如何通过Nagios软件来监控Tomcat服务运行状况,其中主要包括Tomcat Server以及JDBC Pool的运行状态。Nagios的插件中本身并不提供对于Tomcat服务监控的功能,所以要根据Nagios PluginAPI编写自己的脚本,扩展其插件,完成我们所需要的功能。对于Tomcat运行状态信息的获得需通过JMX。
本文参考了Nagios3的官方文档中有关Nagios Plugin部分,以及Tomcat官方文档有关JMX和命令行部分,具体的Tomcat版本是7.0.81(JDK7)。
2.NagiosPlugin API概述
作为一个Nagios插件,无论你是用脚本(如shell、perl)还是用c编译后的可执行程序实现,它必须至少完成两件事,
1、退出时有一个返回值。
2、至少向标准输出设备(STDOUT)输出一行文本。
返回值定义:
Plugin Return Code |
Service State |
Host State |
0 |
OK |
UP |
1 |
WARNING |
UP or DOWN/UNREACHABLE* |
2 |
CRITICAL |
DOWN/UNREACHABLE |
3 |
UNKNOWN |
DOWN/UNREACHABLE |
输出文本至少要一行,其信息主要反映被监控应用、服务的状态。
例如:DISK OK - free space: / 3326 MB (56%);
3.监控Tomcat的实现方法
对于Tomcat运行状况的获得,我们是通过JMX访问Tomcat的方式实现的,通过JVM的queryMBeans方法查询获取具体的Mbean(Thread、JVM、JDBC),根据bean的属性值判断运行状态。
3.1. Tomcat开启RMI
若通过JMX连接Tomcat,需开启Tomcat的RMI。开启需要指定具体端口,具体配置如下,需将如下代码加入Tomcat启动脚本。
export JMX_REMOTE_CONFIG=" -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.password.file=../conf/jmxremote.password -Dcom.sun.management.jmxremote.access.file=../conf/jmxremote.access "
export CATALINA_OPTS="$CATALINA_OPTS $JMX_REMOTE_CONFIG" |
重启tomcat,并检查参数是否生效(通过ps –ef|grep java 查看参数是否已加入,通过netstat –lanp 查看端口是否启动)。
我们在这里选择了需要认证,并配置了访问控制文件。
-Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.password.file=../conf/jmxremote.password -Dcom.sun.management.jmxremote.access.file=../conf/jmxremote.access |
登录用户monitorRole,权限readonly(只读)
cat ../conf/jmxremote.access monitorRole readonly |
登录用户monitorRole以及密码
cat ../conf/jmxremote.password monitorRole tomcat0930 |
3.2. 通过JMX访问Tomcat
通过JMXConnectorFactory类,经JMX协议连接Tomcat的jmxrmi,注意这里需要进行认证。
String jmxURL = "service:jmx:rmi:///jndi/rmi://localhost:8999/jmxrmi"; JMXServiceURL serviceURL;
serviceURL = new JMXServiceURL(jmxURL);
Map map = new HashMap(); String[] credentials = new String[] { "monitorRole", "XXXXX" }; map.put("jmx.remote.credentials", credentials); JMXConnector connector = JMXConnectorFactory.connect(serviceURL, map);
MBeanServerConnection mbsc = connector.getMBeanServerConnection();
|
3.3. Tomcat运行状态信息获得
通过MBeanServerConnection获得具体的MBean。并通过MBean的属性获得运行状态。Thread、JVM、JDBC对应的属性获取方式具体如下。
Thread
ObjectName ObjName = new ObjectName( "Catalina:name=\"http-bio-*\",type=ThreadPool");
Set // System.out.println("MBeanset1.size:" + MBeanset1.size()); System.out.println("#THREAD#"); for (ObjectName obj : mbeanManagerSet) {
ObjectName objectName = new ObjectName(obj.getCanonicalName());
String canonicalName = objectName.getCanonicalName(); // System.out.println("objectInstance : " + objectInstance); System.out.println("+canonicalName : " + canonicalName); MBeanInfo info = mbsc.getMBeanInfo(objectName); MBeanAttributeInfo[] ainfo = info.getAttributes();
// 逐一获得属性值 for (int i = 0; i < ainfo.length; i++) {
String attributeName = ainfo[i].getName(); String attributeinfo = getAttributeByNmae(mbsc, objectName, attributeName); if (!("".equals(attributeinfo) || attributeinfo.isEmpty())) { System.out.println(attributeinfo); } } System.out.println("-canonicalName : " + canonicalName); } } |
JVM
ObjectName heapObjName = new ObjectName("java.lang:type=Memory"); MemoryUsage heapMemoryUsage; System.out.println("#JVM#"); System.out.println("+HeapMemoryUsage"); try { heapMemoryUsage = MemoryUsage.from((CompositeDataSupport) mbsc .getAttribute(heapObjName, "HeapMemoryUsage"));
long maxMemory = heapMemoryUsage.getMax();// 堆最大
long commitMemory = heapMemoryUsage.getCommitted();// 堆当前分配
long usedMemory = heapMemoryUsage.getUsed(); System.out.println(" Max:" + maxMemory); System.out.println(" Committed:" + commitMemory);// 堆当前分配 System.out.println(" HeapPercent:" + (int) (usedMemory * 10000 / commitMemory) + "");// 堆使用率 } catch (AttributeNotFoundException e) { // TODO Auto-generated catch block // e.printStackTrace(); } catch (MBeanException e) { // TODO Auto-generated catch block // e.printStackTrace(); } System.out.println("-HeapMemoryUsage");
|
JDBC
// 获得javax.sql.DataSource信息 ObjectName ObjName = new ObjectName( "Catalina:class=javax.sql.DataSource,context=/*,host=localhost,name=\"*\",type=DataSource");
Set mbeanJDBCSet = mbsc.queryMBeans(ObjName, null); // System.out.println("MBeanset1.size:" + MBeanset1.size()); Iterator MBeansetIterator1 = mbeanJDBCSet.iterator(); System.out.println("#JDBC#"); while (MBeansetIterator1.hasNext()) { ObjectInstance objectInstance = (ObjectInstance) MBeansetIterator1 .next(); ObjectName objectName = objectInstance.getObjectName();
String canonicalName = objectName.getCanonicalName(); // System.out.println("objectInstance : " + objectInstance); System.out.println("+canonicalName : " + canonicalName); MBeanInfo info = mbsc.getMBeanInfo(objectName); MBeanAttributeInfo[] ainfo = info.getAttributes();
// 逐一获得属性值 for (int i = 0; i < ainfo.length; i++) {
String attributeName = ainfo[i].getName(); String attributeinfo = getAttributeByNmae(mbsc, objectName, attributeName); if (!("".equals(attributeinfo) || attributeinfo.isEmpty())) { System.out.println(attributeinfo); } } System.out.println("-canonicalName : " + canonicalName); }
|
3.4. Nrpe Nagios Plugin
check_tomcat脚本逻辑如下(伪代码),
case "$v_cmd" in --JVM) 获取JVM信息 如果获取出错,返回STATE_UNKNOWN状态 如果HeapPercent大于crit,返回STATE_CRITICAL状态 如果HeapPercent大于crit,返回STATE_WARNING状态 返回STATE_OK状态 --JDBC) 获取JDBC信息 v_state_crit=0 v_state_warn=0 逐一处理JDBC 如果maxActive小于等于numActive(活动数已经等于最大值),v_state_crit=1 如果numActive大于0并且v_numIdle小于等于0(有活动且空闲数为零),v_state_warn=1
如果v_state_crit=1,返回STATE_CRITICAL状态 如果v_state_warn=1,返回STATE_WARNING状态 返回STATE_OK状态 --THREAD) 获取Thread信息 v_state_crit=0 v_state_warn=0 逐一处理Thread 如果maxConnections小于等于currentThreadCount(线程数已经等于最大值),v_state_crit=1 如果currentThreadCount小于等于connectionCount(活动数已经达到线程数),v_state_warn=1
如果v_state_crit=1,返回STATE_CRITICAL状态 如果v_state_warn=1,返回STATE_WARNING状态 返回STATE_OK状态 |
3.5. Nagios监控配置
Nrpe端
./libexec下部署check_tomcat.sh脚本,并部署TomcatJMX.class到./libexec/tomcat/com/tomcat/jmx下。
./etc/nrpe.cfg
command[check_tomcat_JDBC]=/usr/local/nagios/libexec/check_tomcat.sh --JDBC command[check_tomcat_JVM]=/usr/local/nagios/libexec/check_tomcat.sh --JVM 9998 9999 command[check_tomcat_THREAD]=/usr/local/nagios/libexec/check_tomcat.sh --THREAD |
Server端
./etc/nagios.cfg
define service{ use tomcat-service host_name linux_XX service_description check-wls-console--JDBC check_command check_nrpe!check_tomcat_JDBC }
define service{ use tomcat-service host_name linux_XX service_description check-wls-console--JVM check_command check_nrpe!check_tomcat_JVM }
define service{ use tomcat-service host_name linux_XX service_description check-wls-console--THREAD check_command check_nrpe!check_tomcat_THREAD } |
验证配置是否正确。
重启监控主机上的nagios服务以及远程主机上的nrpe服务。
通过IE观察监控情况。
图3.1 |
就此配置工作完成。
4.结语
本文介绍了一种通过Nagios监控Tomcat应用的实现方式,按照Nagios Plugin API规则编写自己的Shell脚本实现该功能,并简单的描述了配置过程,提供了Shell源码。希望大家指正。