系统监控一直都是很重要的内容,可以让应用主动通知你系统现在的允许状况。Java世界里面dropwizard提供了系统监控的功能,个人觉得非常好用,主要分为2大块,一块是系统健康监控,一块是系统的运行度量统计。第一篇先介绍健康依赖。
首先在pom文件中加入metrics健康监控包依赖。
<!-- metrics start -->
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>${project-metricsVersion}</version>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-healthchecks</artifactId>
<version>${project-metricsVersion}</version>
</dependency>
<!-- metrics end -->
其次创建健康检查的Scheduled task服务,通过scheduled task把健康信息发送到监控平台,也可以简单记录文件,连续几次不健康后邮件短信通知,现在展示一种简单实现(通过Logger单纯记录健康状态到文件):
/**
*
*/
package com.cloud.demo.service.impl;
import java.util.Map;
import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.codahale.metrics.health.HealthCheck;
import com.codahale.metrics.health.HealthCheck.Result;
import com.codahale.metrics.health.HealthCheckRegistry;
/**
* @author cloudlu
*
*/
public class SystemHealthCheck implements Runnable{
private static final Logger LOG = LoggerFactory.getLogger(SystemHealthCheck.class);
private final static HealthCheckRegistry healthChecks = new HealthCheckRegistry();
public static boolean registerToSysHealthCheck(final String name, final HealthCheck healthCheck){
if(healthChecks.getNames().contains(name)){
return false;
}
healthChecks.register(name, healthCheck);
return true;
}
public void run(){
final Map<String, Result> results = healthChecks.runHealthChecks();
StringBuilder message = null;
for (Entry<String, Result> entry : results.entrySet()) {
message = new StringBuilder(entry.getKey());
if (entry.getValue().isHealthy()) {
message.append(" is healthy: ").append(entry.getValue().getMessage());
LOG.info(message.toString());
} else {
message.append(" is UNHEALTHY: ").append(entry.getValue().getMessage());
LOG.error(message.toString(), entry.getValue().getError());
}
}
}
}
最后把要监控的系统注册到健康服务,并且提供指定回调函数,显示系统状态,例如查看hibernate的sessionfactory状态如下:
/**
*
*/
package com.cloud.demo.service.impl;
import javax.annotation.Resource;
import org.hibernate.SessionFactory;
import org.springframework.orm.jpa.vendor.Database;
import com.codahale.metrics.health.HealthCheck;
/**
* @author cloudlu
*
*/
public class DatabaseHealthCheck extends HealthCheck {
private final static String HEALTHCHECKNAME = DatabaseHealthCheck.class.getSimpleName();
private SessionFactory sessionFactory;
public DatabaseHealthCheck(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public DatabaseHealthCheck(){
SystemHealthCheck.registerToSysHealthCheck(HEALTHCHECKNAME, this);
}
@Override
public HealthCheck.Result check() throws Exception {
if (!sessionFactory.isClosed()) {
return HealthCheck.Result.healthy();
} else {
return HealthCheck.Result.unhealthy("sessionFactory is closed " + sessionFactory.getStatistics());
}
}
}