• 聊聊druid连接池的监控


    本文主要研究一下druid连接池的监控

    init

    com/alibaba/druid/pool/DruidDataSource.java

    public void init() throws SQLException {
    	//......
    	registerMbean();
    	//......
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    DruidDataSource的init方法会执行registerMbean

    registerMbean

    com/alibaba/druid/pool/DruidDataSource.java

        public void registerMbean() {
            if (!mbeanRegistered) {
                AccessController.doPrivileged(new PrivilegedAction() {
                    @Override
                    public Object run() {
                        ObjectName objectName = DruidDataSourceStatManager.addDataSource(DruidDataSource.this,
                                DruidDataSource.this.name);
    
                        DruidDataSource.this.setObjectName(objectName);
                        DruidDataSource.this.mbeanRegistered = true;
    
                        return null;
                    }
                });
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    registerMbean会执行DruidDataSourceStatManager.addDataSource(DruidDataSource.this, DruidDataSource.this.name)

    DruidDataSourceStatManager

    com/alibaba/druid/stat/DruidDataSourceStatManager.java

        public static synchronized ObjectName addDataSource(Object dataSource, String name) {
            final Map instances = getInstances();
    
            MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
            synchronized (instances) {
                if (instances.size() == 0) {
                    try {
                        ObjectName objectName = new ObjectName(MBEAN_NAME);
                        if (!mbeanServer.isRegistered(objectName)) {
                            mbeanServer.registerMBean(instance, objectName);
                        }
                    } catch (JMException ex) {
                        LOG.error("register mbean error", ex);
                    }
    
                    DruidStatService.registerMBean();
                }
            }
    
            ObjectName objectName = null;
            if (name != null) {
                try {
                    objectName = new ObjectName("com.alibaba.druid:type=DruidDataSource,id=" + name);
                    mbeanServer.registerMBean(dataSource, objectName);
                } catch (Throwable ex) {
                    LOG.error("register mbean error", ex);
                    objectName = null;
                }
            }
    
            if (objectName == null) {
                try {
                    int id = System.identityHashCode(dataSource);
                    objectName = new ObjectName("com.alibaba.druid:type=DruidDataSource,id=" + id);
                    mbeanServer.registerMBean(dataSource, objectName);
                } catch (Throwable ex) {
                    LOG.error("register mbean error", ex);
                    objectName = null;
                }
            }
    
            instances.put(dataSource, objectName);
            return objectName;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    DruidDataSourceStatManager的addDataSource方法通过mbeanServer.registerMBean(dataSource, objectName)将DruidDataSource注册到mbeanServer中,而DruidDataSource则实现了DruidDataSourceMBean接口

    DruidDataSourceMBean

    public interface DruidDataSourceMBean extends DruidAbstractDataSourceMBean {
        long getResetCount();
    
        boolean isEnable();
    
        String getUrl();
    
        void shrink();
    
        int removeAbandoned();
    
        String dump();
    
        int getWaitThreadCount();
    
        int getLockQueueLength();
    
        long getNotEmptyWaitCount();
    
        int getNotEmptyWaitThreadCount();
    
        long getNotEmptySignalCount();
    
        long getNotEmptyWaitMillis();
    
        long getNotEmptyWaitNanos();
    
        void resetStat();
    
        boolean isResetStatEnable();
    
        void setResetStatEnable(boolean resetStatEnable);
    
        String getVersion();
    
        void setPoolPreparedStatements(boolean poolPreparedStatements);
    
        int getActivePeak();
    
        int getPoolingPeak();
    
        Date getActivePeakTime();
    
        Date getPoolingPeakTime();
    
        long getErrorCount();
    
        ObjectName getObjectName();
    
        void clearStatementCache() throws SQLException;
    
        long getDiscardCount();
    
        void setStatLoggerClassName(String className);
    
        long getTimeBetweenLogStatsMillis();
    
        void setTimeBetweenLogStatsMillis(long timeBetweenLogStatsMillis);
    
        void setConnectionProperties(String connectionProperties);
    
        int fill() throws SQLException;
    
        int fill(int toCount) throws SQLException;
    
        boolean isUseGlobalDataSourceStat();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    DruidDataSourceMBean按jmx规范命名以MBean结尾,它定义了一系列的getter和操作方法,它还继承了DruidAbstractDataSourceMBean

    DruidAbstractDataSourceMBean

    com/alibaba/druid/pool/DruidAbstractDataSourceMBean.java

    public interface DruidAbstractDataSourceMBean {
        int getLoginTimeout();
    
        String getDbType();
    
        String getName();
    
        int getInitialSize();
    
        String getUsername();
    
        String getUrl();
    
        String getDriverClassName();
    
        long getConnectCount();
    
        long getCloseCount();
    
        long getConnectErrorCount();
    
        int getPoolingCount();
    
        long getRecycleCount();
    
        int getActiveCount();
    
        long getCreateCount();
    
        long getDestroyCount();
    
        long getCreateTimespanMillis();
    
        long getCommitCount();
    
        long getRollbackCount();
    
        long getStartTransactionCount();
    
        int getQueryTimeout();
    
        int getTransactionQueryTimeout();
    
        String getValidationQuery();
    
        int getValidationQueryTimeout();
    
        int getMaxWaitThreadCount();
    
        long getTimeBetweenEvictionRunsMillis();
    
        long getMinEvictableIdleTimeMillis();
    
        boolean isRemoveAbandoned();
    
        long getRemoveAbandonedTimeoutMillis();
    
        List getActiveConnectionStackTrace();
    
        List getFilterClassNames();
    
        boolean isTestOnBorrow();
    
        void setTestOnBorrow(boolean testOnBorrow);
    
        boolean isTestOnReturn();
    
        boolean isTestWhileIdle();
    
        void setTestWhileIdle(boolean testWhileIdle);
    
        boolean isDefaultAutoCommit();
    
        Boolean getDefaultReadOnly();
    
        Integer getDefaultTransactionIsolation();
    
        String getDefaultCatalog();
    
        boolean isPoolPreparedStatements();
    
        boolean isSharePreparedStatements();
    
        long getMaxWait();
    
        int getMinIdle();
    
        int getMaxIdle();
    
        long getCreateErrorCount();
    
        int getMaxActive();
    
        void setMaxActive(int maxActive);
    
        long getTimeBetweenConnectErrorMillis();
    
        int getMaxOpenPreparedStatements();
    
        long getRemoveAbandonedCount();
    
        boolean isLogAbandoned();
    
        void setLogAbandoned(boolean logAbandoned);
    
        long getDupCloseCount();
    
        boolean isBreakAfterAcquireFailure();
    
        int getConnectionErrorRetryAttempts();
    
        int getMaxPoolPreparedStatementPerConnectionSize();
    
        void setMaxPoolPreparedStatementPerConnectionSize(int maxPoolPreparedStatementPerConnectionSize);
    
        String getProperties();
    
        int getRawDriverMinorVersion();
    
        int getRawDriverMajorVersion();
    
        Date getCreatedTime();
    
        String getValidConnectionCheckerClassName();
    
        long[] getTransactionHistogramValues();
    
        void setTransactionThresholdMillis(long transactionThresholdMillis);
    
        long getTransactionThresholdMillis();
    
        long getPreparedStatementCount();
    
        long getClosedPreparedStatementCount();
    
        long getCachedPreparedStatementCount();
    
        long getCachedPreparedStatementDeleteCount();
    
        long getCachedPreparedStatementAccessCount();
    
        long getCachedPreparedStatementMissCount();
    
        long getCachedPreparedStatementHitCount();
    
        boolean isUseOracleImplicitCache();
    
        void setUseOracleImplicitCache(boolean useOracleImplicitCache);
    
        int getDriverMajorVersion();
    
        int getDriverMinorVersion();
    
        String getExceptionSorterClassName();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155

    DruidAbstractDataSourceMBean定义了暴露给jmx的一系列方法

    getStatDataForMBean

    com/alibaba/druid/pool/DruidDataSource.java

        public Map getStatDataForMBean() {
            try {
                Map map = new HashMap();
    
                // 0 - 4
                map.put("Name", this.getName());
                map.put("URL", this.getUrl());
                map.put("CreateCount", this.getCreateCount());
                map.put("DestroyCount", this.getDestroyCount());
                map.put("ConnectCount", this.getConnectCount());
    
                // 5 - 9
                map.put("CloseCount", this.getCloseCount());
                map.put("ActiveCount", this.getActiveCount());
                map.put("PoolingCount", this.getPoolingCount());
                map.put("LockQueueLength", this.getLockQueueLength());
                map.put("WaitThreadCount", this.getNotEmptyWaitThreadCount());
    
                // 10 - 14
                map.put("InitialSize", this.getInitialSize());
                map.put("MaxActive", this.getMaxActive());
                map.put("MinIdle", this.getMinIdle());
                map.put("PoolPreparedStatements", this.isPoolPreparedStatements());
                map.put("TestOnBorrow", this.isTestOnBorrow());
    
                // 15 - 19
                map.put("TestOnReturn", this.isTestOnReturn());
                map.put("MinEvictableIdleTimeMillis", this.minEvictableIdleTimeMillis);
                map.put("ConnectErrorCount", this.getConnectErrorCount());
                map.put("CreateTimespanMillis", this.getCreateTimespanMillis());
                map.put("DbType", this.dbTypeName);
    
                // 20 - 24
                map.put("ValidationQuery", this.getValidationQuery());
                map.put("ValidationQueryTimeout", this.getValidationQueryTimeout());
                map.put("DriverClassName", this.getDriverClassName());
                map.put("Username", this.getUsername());
                map.put("RemoveAbandonedCount", this.getRemoveAbandonedCount());
    
                // 25 - 29
                map.put("NotEmptyWaitCount", this.getNotEmptyWaitCount());
                map.put("NotEmptyWaitNanos", this.getNotEmptyWaitNanos());
                map.put("ErrorCount", this.getErrorCount());
                map.put("ReusePreparedStatementCount", this.getCachedPreparedStatementHitCount());
                map.put("StartTransactionCount", this.getStartTransactionCount());
    
                // 30 - 34
                map.put("CommitCount", this.getCommitCount());
                map.put("RollbackCount", this.getRollbackCount());
                map.put("LastError", JMXUtils.getErrorCompositeData(this.getLastError()));
                map.put("LastCreateError", JMXUtils.getErrorCompositeData(this.getLastCreateError()));
                map.put("PreparedStatementCacheDeleteCount", this.getCachedPreparedStatementDeleteCount());
    
                // 35 - 39
                map.put("PreparedStatementCacheAccessCount", this.getCachedPreparedStatementAccessCount());
                map.put("PreparedStatementCacheMissCount", this.getCachedPreparedStatementMissCount());
                map.put("PreparedStatementCacheHitCount", this.getCachedPreparedStatementHitCount());
                map.put("PreparedStatementCacheCurrentCount", this.getCachedPreparedStatementCount());
                map.put("Version", this.getVersion());
    
                // 40 -
                map.put("LastErrorTime", this.getLastErrorTime());
                map.put("LastCreateErrorTime", this.getLastCreateErrorTime());
                map.put("CreateErrorCount", this.getCreateErrorCount());
                map.put("DiscardCount", this.getDiscardCount());
                map.put("ExecuteQueryCount", this.getExecuteQueryCount());
    
                map.put("ExecuteUpdateCount", this.getExecuteUpdateCount());
    
                return map;
            } catch (JMException ex) {
                throw new IllegalStateException("getStatData error", ex);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    DruidDataSource的getStatDataForMBean定义了给jmx的所有监控项

    DruidDataSourceUtils

    com/alibaba/druid/util/DruidDataSourceUtils.java

        public static Map getStatDataForMBean(Object druidDataSource) {
            if (druidDataSource.getClass() == DruidDataSource.class) {
                return ((DruidDataSource) druidDataSource).getStatDataForMBean();
            }
    
            try {
                Method method = druidDataSource.getClass().getMethod("getStatDataForMBean");
                Object obj = method.invoke(druidDataSource);
                return (Map) obj;
            } catch (Exception e) {
                LOG.error("getStatDataForMBean error", e);
                return null;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    DruidDataSourceUtils提供了静态方法用于获取监控项

    小结

    DruidDataSource的init方法会执行registerMbean,把自身注册到mbeanServer,它实现了DruidDataSourceMBean接口;而DruidDataSourceUtils提供了静态方法用于获取监控项,它使用的是DruidDataSource的getStatDataForMBean方法(貌似没直接给到jmx),可以利用该方法把指标暴露给micrometer,之后就可以利用micrometer的集成能力输出到各个监控平台。

  • 相关阅读:
    【ES】springboot集成ES
    【算法集训】基础算法:基础排序 - 冒泡排序
    观后感《经济逆境中,普通人的机会在哪里?》
    SSL发送邮件时如何配置客户端确保安全性?
    2022最新IntellJ IDEA诺依开发部署文档
    C++ Primer Plus第十三章编程练习答案
    漂亮的pyqt6皮肤 PyOneDark_Qt_Widgets_Modern_GUIPublic
    FTP客户端lftp
    vue实战中的一些小技巧
    Git高频命令【最实用命令】
  • 原文地址:https://blog.csdn.net/hello_ejb3/article/details/133412592