前言
相信大家都很熟悉阿里巴巴的druid数据库连接池。在国内使用数据库操作时,大多数都会引用druid的话。当然,今天不是讲如何利用druid,而是分析druid的监听。我们先回顾一下druid是什么?
介绍
1。Druid是阿里巴巴开源的JDBC应用组件。它由三部分组成:
Druid Driver:Agent Driver,可以提供基于Filter-Chain模式的插件系统。
Druid DataSource:高效且可管理的数据库连接池。
SQLParser:实用SQL语法分析
2。通过Druid连接池中间件,我们可以实现:
您可以监控数据库访问性能。Druid提供了强大的内置StatFilter插件,可以提供详细的SQL执行性能统计数据,有助于在线分析数据库访问性能。
替代传统的DBCP和C3P0连接池中间件。Druid提供了一个高效、强大、可扩展的数据库连接池。
数据库密码加密。直接将数据库密码写入配置文件中很容易导致安全问题。DruidDruiver和Druid数据源都支持PasswordCallback。
SQL执行日志,Druid提供了不同的LogFilter,可以支持Common-Logging、Log4j和JdkLog。您可以根据需要选择相应的LogFilter来监控您应用程序的数据库访问情况。
扩展 JDBC。如果您有 JDBC 层的编程需求,可以利用Druid提供的 Filter-Chain 机制,轻松编写 JDBC 层的扩展插件
监控
druid最大的特点就是有相应的监控,可以帮助我们查看SQL的执行日志、慢SQL语句、SQL执行的性能、预防SQL注入。
数据来源
数据源菜单显示数据库连接池的基本信息,如连接地址、连接类型、最大连接数、最小连接数、初始连接数等信息。
可以通过逻辑连接打开次数和逻辑连接关闭次数来判断系统中是否存在未关闭的连接(正常情况下是打开次数和关闭次数应该是一样的)
SQL监控
SQL监控显示系统已执行的每条SQL语句的执行状态。通过执行次数、执行时间、最慢时间、事务数、错误数、最大并发数、执行时间分布等统计维度展示。
1。执行次数:这条sql语句已被执行的次数 2.执行时间:这条sql语句的累计执行时间(单位:毫秒) 3.最慢:这条sql语句最慢的执行时间(单位:毫秒) 4、执行时间分布【- – – – – – – -】:这8 – 代表8个耗时区间的次数,从左到右:0-1毫秒次、1-10毫秒次、10-100毫秒、 100-1000 毫秒、1-10 秒、10-100 秒、100-1000 秒、大于 1000 秒。
网络应用程序
主要统计本应用的并发数、请求数、事务提交、事务回滚等信息。它还统计该应用程序在各种操作系统和浏览器上的访问次数。
SQL 防火墙
分为防御统计、表访问统计、函数调用统计、SQL防御统计-白名单、SQL防御统计-黑名单。疑似SQL注入的SQL语句将被拦截并出现在SQL防御统计-黑名单中
请求URL监控
统计应用中每个URL的访问次数、请求时间、并发数等信息
会话监控
显示应用中会话的请求时间、请求数量、最大并发数等数据
问题1
我们看到了druid的监控能力有多么强大,同时我们也发现了一个大问题,如图
druid控制台针对每个实例,不同实例有不同的druid控制台;但是在生产环境中,会有多个实例,那么就会有多个监控平台,那么我们要运维/开发,人们查看起来很麻烦,需要打开多个控制台。监测数据不能作为一个整体来看待。
如何解决?
源码分析
我们先来看看druid的监控功能是如何实现的?
我们看一下Druid DataSource核心类,它有一个LogStatsThread线程
私有 LogStatsThread logStatsThread;
在DruidDataSource初始化init方法中,调用了createAndLogThread方法。再看一下createAndLogThread方法。当timeBetweenLogStatsMillis属性大于0时,LogStatsThread线程被实例化。
我们来看看LogStatsThread线程做了什么事情
LogStatsThread 线程不断循环调用 logStats 方法,每次休眠 timeBetweenLogStatsMillis 毫秒。那么我们就知道这个参数的本质是多少毫秒执行logStats方法。
上面的代码表示将数据监控存储在DruidDataSourceStatValue实例中,然后由statLogger对象记录。存储在哪里由 statLogger 决定。
druid默认的DruidDataSourceStatLogger接口实现DruidDataSourceStatLoggerImpl,
可以看到,Druid以Json的形式输出日志。具体的数据处理是在log(Druid DataSourceStatValue)方法中进行的。这个方法也是我们后面需要用到的。
计划1
Druid默认的持久化方式是文件记录。如果我们想要自定义监控记录的持久化方法,我们需要自定义StatLogger。参考上面StatLogger的默认实现,我们可以定义一个简单的StatLogger,如下所示:
这里我们重写了log(Druid DataSourceStatValue)方法,定制了一个简单的StatLogger。接下来,我们需要在数据源中配置这个statLogger。我们在配置文件中的druid节点下添加如下配置:
日志统计毫秒之间的时间:60000 统计记录器:
在配置过程中发现stat-logger对应的是一个Druid DataSourceStatLoggerAdapter对象,而yml配置文件只支持基本数据类型以及Map、List等类型。查看源码可以发现,Druid AbstractDataSource类有如下定义:
支持直接设置statLogger对象,也支持通过类名设置。返回配置文件,找到这个没有类名的配置项,如下:
由于无法直接通过配置文件进行配置,所以我们以配置类的形式配置Druid数据源,并新建一个Druid配置类,如下所示:
其中@ConfigurationProperties 表示配置的属性。这里,配置文件中以 spring.datasource.druid 为前缀的值映射到 DataSource 对象的同名属性。在这个方法中,我们将 DatSource 的 statLogger 设置为我们自定义的 StatLogger。
这样配置后我们可以看到每10秒就会持久化一次监控数据。
问题2
我们仔细看看上面的方案,如图
上述方案会存在一些问题