Druid监控模块分析(2)

上一章我们分析了,Druid实现监控功能的核心组件,JMX技术,这一章我们分析,Druid如何利用JMX实现指标监控的。

 一.监控加载的入口

Druid通过何种方法把监控指标的相关代码运行起来的?答案就在下面:

 public void init() throws SQLException {
   
   //加载SPI中的Filter类,Filter类可以通过AutoLoad标签,来实现动态加载。默认不配置是主动加载
   initFromSPIServiceLoader();
  
   //通过jdbc连接的方式配置filter过滤器
    if (this.jdbcUrl != null) {
                this.jdbcUrl = this.jdbcUrl.trim();
                //初始化jdbc:wrap-jdbc:driver=rawClassName:filters=  ,  :name=:  jmx= 
                initFromWrapDriverUrl();
    }
   

    下面这个方法是核心方法:先调用初始化方法
    for (Filter filter : filters) {
         filter.init(this);
    }

}

Druid采用的是一种插件的方式,把监控相关的代码,插入到整个流程中去,这样做的好处,就是扩展性更强。并且它也提供了可以自定义实现的接口。所有的监控指标都存在StateFilter中。

二.开启监控方法

我们来思考一下,为啥监控方法采用filter来定义,其实细想,监控实现的功能--> 对各种指标的统计 --->如何统计各种指标--->数据在哪里产生就需要在哪里进行统计-->如果需要统计连接数,查询数,关闭数---->就需要在调用这些jdbc的原生方法时采用拦截的技术,其实就是通过拦截器在内部初始化代理类,对外暴露代理类,代理类包裹真实类,上层框架无感知,在调用这些方法时,就可以通过在代理类代理的方法内部,在调用真实方法之前或者之后做些统计的工作。

 

/**
  先做初始化动作,就是把外部传进来的参数,初始化到内部对象中
**
/
public void init(DataSourceProxy dataSource) {
        lock.lock();
        try {
            if (this.dbType == null) {
                this.dbType = DbType.of(dataSource.getDbType());
            }
            //通过外部的properties给内部的属性初始化
            configFromProperties(dataSource.getConnectProperties());
            configFromProperties(System.getProperties());
        } finally {
            lock.unlock();
        }
    }

三.通过FilterChain创建filterChain中保存的过滤器的连接

public DruidPooledConnection getConnection(long maxWaitMillis) throws SQLException {

        //先初始化
        init();

        //再创建连接
        if (filters.size() > 0) {
            FilterChainImpl filterChain = new FilterChainImpl(this);
            return filterChain.dataSource_connect(this, maxWaitMillis);
        } else {
            return getConnectionDirect(maxWaitMillis);
        }
    }

FilterChainImpl是个核心的类,我们看看这个类中包含什么内容

public class FilterChainImpl implements FilterChain {

    //当前的list中的下标
    protected int                 pos = 0;

    //里面包含了  List<filter> list 过滤器集合
    private final DataSourceProxy dataSource;

    //责任链中过滤器的数量
    private final int             filterSize;

}

其实就是经典的责任链模式中的成员变量,下面是整个初始化过程

  public DruidPooledConnection dataSource_connect(DruidDataSource dataSource, long maxWaitMillis) throws SQLException {
        //如果当前的下标比长度小,就先调用下一个过滤器
        if (this.pos < filterSize) {
            //label标签
            DruidPooledConnection conn = nextFilter().dataSource_getConnection(this, dataSource, maxWaitMillis);
            return conn;
        }

        return dataSource.getConnectionDirect(maxWaitMillis);
    }

上面这几行代码就是整个初始化的关键,其调用顺序是这样的。

首先: 1号过滤器--->2---->3  此时所有的过滤器都停在label标签这一行。

 调用3时,开启下一轮调用,因为3个最后一个过滤器,所以3调用的方法就会有返回值。3就会返回了, 此时又回到2,2返回又回到1,最后整个调用栈结束。

3-->2--->1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值