SpringBoot应用中监控tomcat,druid连接池状态
这篇文章记录一下如何在spring boot中监控tomcat,druid连接池状态,之前我写过一篇文章介绍过类似的,具体背景和监控数据的收集部分这里就不赘述,可以参考在SPRING BOOT应用监控线程池的状态
背景
随着流量的增大,我们急需监控各个微服务部署的tomcat和数据库连接池状态,以此来了解线上连接池配置是否满足要求,不存在性能上的问题。
数据收集
JMX
再介绍怎么监控连接池状态之前,先来了解一下JMX, JMX在Java编程语言中定义了应用程序以及网络管理和监控的体系结构、设计模式、应用程序接口以及服务。通常使用JMX来监控系统的运行状态或管理系统的某些方面,比如清空缓存、重新加载配置文件等。
tomcat和druid在启动后都会在JMX中注册自己的Mbean, 其中Mbean有关于连接池状态的属性,因此只需要定时读取Mbean中的这部分属性就能做到对线程池的监控。
怎么试着查看JMX呢?最简单的办法就是通过jvisualvm,打开已经启动的spring boot项目,当然前提是要在jvisualvm中提前安装好mbeans的插件,之后我们能发现有一个Mbeans标签,点击它就能看到所有注册到JMX的Mbean, 其中就有Tomcat和Druid的Mbean,顺着它们的树状结构查看它们支持的所有属性值,这些属性值就是正在运行的spring boot程序的当前状态,挑出我们最关心的属性继续往下看。
还是和之前一样利用spring boot actuator, 它能和statsd集成,并定时将/metrics中的监控数据发送出去,因此我们只需要实现PublicMetrics接口,而在metrics方法中读取tomcat和druid的Mbean数据,具体可以参考下面的代码:
监控Tomcat连接池
@Component
public class TomcatPublishMetrics implements PublicMetrics {
public static final Logger LOG = LoggerFactory.getLogger(TomcatPublishMetrics.class);
@Autowired
private MBeanServer mbeanServer;
@Override
public Collection<Metric<?>> metrics() {
try {
Set<ObjectName> objectNames = mbeanServer.queryNames(new ObjectName("Tomcat:type=ThreadPool,*"), null);
Collection<Metric<?>> result = new ArrayList<>();
if (objectNames != null && objectNames.size() == 1) {
for (ObjectName objectName : objectNames) {
int maxThreads = (Integer) mbeanServer.getAttribute(objectName, "maxThreads");
int currentThreadCount = (Integer) mbeanServer.getAttribute(objectName, "currentThreadCount");
int currentThreadsBusy = (Integer) mbeanServer.getAttribute(objectName, "currentThreadsBusy");
long connectionCount = (Long) mbeanServer.getAttribute(objectName, "connectionCount");
int maxConnections = (Integer) mbeanServer.getAttribute(objectName, "maxConnections");
result.add(new Metric<Number>("tomcat.thread.busy", currentThreadsBusy, new Date()));
result.add(new Metric<Number>("tomcat.thread.max", maxThreads, new Date()));
result.add(new Metric<Number>("tomcat.thread.current", currentThreadCount, new Date()));
result.add(new Metric<Number>("tomcat.thread.connectionCount", connectionCount, new Date()));
result.add(new Metric<Number>("tomcat.thread.maxConnections", maxConnections, new Date()));
}
} else {
LOG.warn("Tomcat thread pool monitor failed");
}
return result;
} catch (Exception e) {
LOG.error("Tomcat thread pool monitor exception", e);
}
return Collections.emptyList();
}
}
监控Druid连接池
@Component
public class DruidPoolPublishMetrics implements PublicMetrics {
public static final Logger LOG = LoggerFactory.getLogger(DruidPoolPublishMetrics.class);
@Autowired
private MBeanServer mbeanServer;
@Override
public Collection<Metric<?>> metrics() {
try {
Set<ObjectName> objectNames = mbeanServer.queryNames(new ObjectName("com.alibaba.druid.pool:type=DruidDataSource,*"), null);
Collection<Metric<?>> result = new ArrayList<>();
if (objectNames != null && objectNames.size() == 1) {
for (ObjectName objectName : objectNames) {
long errorCount = (Long) mbeanServer.getAttribute(objectName, "ErrorCount");
int waitThreadCount = (Integer) mbeanServer.getAttribute(objectName, "WaitThreadCount");
long resetCount = (Long) mbeanServer.getAttribute(objectName, "ResetCount");
int activeCount = (Integer) mbeanServer.getAttribute(objectName, "ActiveCount");
long rollbackCount = (Long) mbeanServer.getAttribute(objectName, "RollbackCount");
int maxActive = (Integer) mbeanServer.getAttribute(objectName, "MaxActive");
result.add(new Metric<Number>("druid.pool.errorCount", errorCount, new Date()));
result.add(new Metric<Number>("druid.pool.waitThreadCount", waitThreadCount, new Date()));
result.add(new Metric<Number>("druid.pool.resetCount", resetCount, new Date()));
result.add(new Metric<Number>("druid.pool.activeCount", activeCount, new Date()));
result.add(new Metric<Number>("druid.pool.rollbackCount", rollbackCount, new Date()));
result.add(new Metric<Number>("druid.pool.maxActive", maxActive, new Date()));
}
} else {
LOG.warn("DruidPool monitor failed");
}
return result;
} catch (Exception e) {
LOG.error("DruidPool monitor exception", e);
}
return Collections.emptyList();
}
}
总结
这篇文章介绍了通过读取JMX中相应的Mbean的数据进行收集并监控,如果其他的监控指标注册在JMX中,例如对redis的连接池,也可以采用类似的方法收集。
————————————————
以上是 SpringBoot应用中监控tomcat,druid连接池状态 的全部内容, 来源链接: utcz.com/z/516267.html