拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Druid连接池崩溃复盘:慢SQL、连接泄漏与监控告警实战

凌晨两点半监控群里开始刷屏。先是数据库连接超时的告警紧接着业务方反馈下单接口大面积报错。我第一时间打开Druid监控页面屏幕上的数据把我吓了一跳——activeCount已经顶到了maxActivewaitingThreadCount还在疯涨SQL监控列表里全是慢查询记录。这就是这次线上事故的开场。这篇文章把这次Druid连接池崩溃的前因后果、排查思路和后续加固方案完整复盘一遍。同时会把若依框架集成Druid做数据库密码加密、监控页面配置这些高频话题一起讲透尤其会把我踩过的一些坑和线上排查技巧交代清楚。做Java开发的同学、维护Spring Boot项目的同学这篇文章都值得花几分钟看完。1. 故障现场与初步判断1.1 监控页面拉响的警报长什么样线上环境用的Druid连接池最大活跃连接数maxActive配置的是50。正常情况下凌晨两点这个时间段的活跃连接数应该在个位数到十几之间。但那晚打开监控页面数据源面板上的数字非常刺眼ActiveCount活跃连接数: 50顶满PoolingCount池中空闲连接数: 0一个不剩WaitThreadCount等待获取连接的线程数: 持续上升一度到了60多事务提交/回滚次数异常回滚次数远超平时这些数据组合起来说明一个很明确的现状应用需要数据库连接但连接已经全部分配出去且没有归还新请求只能阻塞在getConnection()上等待。Druid的maxWait我设置的是10000毫秒超过10秒拿不到连接就直接抛CannotGetJdbcConnectionException外层再包装成业务异常抛给前端用户看到的就是系统繁忙请稍后重试。这时候不要急着重启应用。重启能解决一部分问题但如果根因是连接泄漏重启后只能换来短暂的假健康跑一段时间又会爆炸。我当时做的第一件事是保留现场把Druid监控页面里数据源页签的具体数据截图然后去捞应用日志里报错的线程堆栈。1.2 先从异常堆栈判断故障方向异常堆栈是定位数据库连接问题的第一手资料。常见的堆栈有这么几类每一类对应的排查方向完全不同。第一类是获取连接超时的堆栈里面会明确出现Druid自己的代码路径比如com.alibaba.druid.pool.DruidDataSource.getConnection()同时报出wait millis 10000, active 50, maxActive 50这类信息。这一行参数非常关键它告诉我池子里50个连接全部被占用没有空闲可用。这个参数在日志里看比在监控页面翻半天还准。第二类是连接有效性校验失败的堆栈比如ValidationQuery执行失败、Communications link failure、Connection is not available, request timed out。这类堆栈说明池中部分连接可能已经和数据库断开但Druid没有及时剔除导致后续请求拿到坏连接。引发原因可能是网络抖动、数据库端wait_timeout超时回收了空闲连接、或者防火墙的interactive_timeout配置太短。第三类是业务线程自己堆栈里卡在DruidPooledConnection.handleConnectionIO或者JDBC驱动执行SQL的地方这种往往是SQL本身出了问题查询跑太久一直不返回连接被事务牢牢攥着。我当时在日志里看到的组合是大量wait millis 10000超时异常SQL监控里紧接着出现一堆执行时间上千毫秒的慢查询同时活跃连接数一直维持在高位不回落。这说明不是一次性拿到坏连接的问题而是有SQL在执行路径上堵车了连接被长期占住不放。2. 连接池崩溃的根因定位2.1 连接泄漏最常见的元凶连接池崩溃第一个要怀疑的就是连接泄漏。所谓连接泄漏就是代码里获取了Connection之后没有正确关闭。Druid有个杀手锏叫removeAbandoned它能把超过指定时间还没归还的连接强行回收掉。但这里有个天然的矛盾removeAbandonedtrue时如果一个线程执行长SQL超过设定阈值连接会被Druid强制回收。但这个线程自己还在用这个连接写数据结果就是连接被人从手里抢走后续执行直接报错数据一致性还可能出问题。removeAbandonedfalse时泄漏的连接永远不被回收时间一长池子必定被耗尽。我那次遇到的问题恰恰是这两种情况混合在一起。业务代码里有一个批量导入的功能开了事务在try块里for循环处理成千上万条记录每条记录都走一次数据库IO。连接本身倒是只在事务开始时获取一次但整个事务因为数据量太大执行时间超过了分钟级。服务端配置了removeAbandonedTimeout300按说不至于被回收。但问题是这个批量逻辑里还在内部嵌套调用了一个JdbcTemplate查询这个查询在子线程里执行子线程自己又去拿了一次连接而子线程的返回结果没等它跑完就丢了连接也没人关闭——这不是事务连接泄漏而是独立连接的泄漏。排查方法也很直接去Druid监控页面的连接池信息里看处于active状态的连接它们对应的JDBC语句、最近一次执行的SQL、以及创建时所在的线程堆栈。如果你的Druid版本支持getActiveConnectionStackTrace()能直接看到每个活跃连接是被哪个线程拿走的、现在停在哪个代码位置。我习惯在故障时用jstack抓一份应用线程快照再把Druid中active连接的堆栈对齐来看基本能锁定是哪一段代码没关连接。这里强调一个代码习惯任何时候获取了Connection关闭动作要放在finally里或者直接用try-with-resources。事务注解Transactional只管事务边界管不了你手动获取的连接。尤其是用原生JDBC、JdbcTemplate混编的老代码最容易出现池子里的连接明明没超时但就是一直不减的现象。2.2 慢SQL与长事务在偷偷占坑连接泄漏排查清楚之后还有一个被很多人忽略的问题慢SQL把连接池占满了。我遇到过这样一个案例凌晨有一个定时任务在跑报表统计SQL长这样SELECT ... FROM order_detail o LEFT JOIN order_info i ON o.order_id i.id WHERE o.create_time BETWEEN ? GROUP BY o.user_id这条SQL涉及两张百万级的大表关联条件上没走索引create_time上也没有合适的索引。结果单条SQL跑了3秒多。正常情况下并发不高没关系但上游偏偏在凌晨有其他批量接口在调用两者叠加几分钟内就把50个连接全部占住了。Druid的maxWait机制让后续的请求继续排队排队线程又占用业务线程池里的线程Tomcat的线程也被拖垮最终整个服务表现为挂掉。慢SQL占坑的典型特征有三个活跃连接数高但每个连接的持续时间都很长。SQL监控里MaxTimes和TotalTime数值暴涨执行次数不多但总耗时很高。等待线程数和活跃连接数呈正相关增长。如果你的监控页面能看到每个连接当前执行的SQL立刻就能定位是哪条慢SQL。我当时就是直接用Druid监控页面的SQL监控列表按总耗时倒序看到那条报表SQL每次执行耗时3.2秒总共执行了40多次几乎把整个池子gg了。2.3 配置参数不合理导致的连锁反应连接池崩了很多时候不全是代码的锅配置参数不合理也会埋雷。有一个经典的配置组合陷阱是testOnBorrowtrue加validationQuery太重。假设validationQuery配的是一条复杂SQL而非SELECT 1那么每次从池子里拿连接都要先执行一次校验SQL在高并发场景下校验请求本身就会冲击数据库反而把连接池拖垮。正确做法是testOnBorrow改为falsetestWhileIdle改为truevalidationQuery用SELECT 1另一个坑是maxActive配得太满。有人觉得连接数越大越好把maxActive设成200结果数据库最大连接数是150应用一启动或者高并发一来数据库先被连接打挂。连接池的上限要根据数据库的承受能力来设一般经验是单实例数据库连接最多给到100到150应用多个实例时要均分留足缓冲。还要注意timeBetweenEvictionRunsMillis和minEvictableIdleTimeMillis的配合。默认的timeBetweenEvictionRunsMillis是60000毫秒每60秒检测一次空闲连接。如果minEvictableIdleTimeMillis设置太短空闲连接会被频繁回收低峰期再请求时又要重新建立连接反而增加延迟。建议minEvictableIdleTimeMillis不低于3000005分钟这样既保证连接不被数据库端提前吃掉又不会频繁建连。下面是那次事故之后我在配置上整理的一份基准参数适合大部分中小型Spring Boot项目参数建议值说明initialSize10启动时创建的连接数minIdle10最小空闲连接数maxActive50按数据库上限和应用并发综合评估maxWait10000获取连接最大等待时间单位毫秒timeBetweenEvictionRunsMillis60000空闲连接检测周期minEvictableIdleTimeMillis300000空闲连接存活时间下限validationQuerySELECT 1连接有效性校验SQLtestWhileIdletrue空闲时校验连接testOnBorrowfalse取出时不校验降低开销testOnReturnfalse归还时不校验removeAbandonedfalse生产环境慎开必须开则调大超时maxPoolPreparedStatementPerConnectionSize20PSCache大小提升性能这套参数不是万能的但能覆盖大多数常规业务场景。后面我会把每个参数的判断逻辑讲清楚。3. 若依框架集成Druid数据库密码加密实战3.1 为什么一定要做密码加密很多人把数据库密码明文写在application.yml里理由是内网环境别人看不到。但现实是配置文件经常会因为代码仓库泄露、测试环境拷给外包、甚至截图发群里等方式流出。一旦有人拿到生产环境的配置文件就等于拿到了数据库的钥匙。等保测评、内部安全审计明文密码都是重大问题。Druid自带的ConfigTools能解决这个问题。它的原理很巧妙用非对称加密算法生成公钥和私钥私钥用来加密明文密码得到密文后将密文和公钥配置在项目里。应用启动时Druid的ConfigFilter用公钥去解密密文还原出真实密码去建立连接。因为私钥只在生成密文时用到一次后续项目中完全不保存私钥即使配置文件泄露别人手里只有密文和公钥也没法反推明文密码。3.2 ConfigTools生成密钥的完整流程生成密钥不需要写代码直接用Druid的jar包命令行执行就行。前提是你本地有对应版本的druid.jar版本建议跟项目中使用的一致。先确认Druid版本然后执行java -cp druid-1.2.20.jar com.alibaba.druid.filter.config.ConfigTools 你的数据库密码执行完成之后终端会输出三行信息privateKey私钥绝对不能提交到配置文件中publicKey公钥可以配置在部署环境的配置中心或本地配置里password加密后的密文用它替换原来的明文密码举个例子假设我的密码是MyPssw0rd生成后得到类似这样的输出privateKey:MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEA... publicKey:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAM5m0W... password:jYb1x0QYxKjRYN9j...实操时建议把私钥打印到终端后就地销毁不要保存到项目里。真要留存存到本机一个只有自己有权限读的文件里并且设置文件权限600。因为私钥一旦泄露加密等于没有做。然后修改application.yml中的数据源配置。最直接的方式是在Druid的connection-properties里开启解密spring: datasource: druid: username: root password: jYb1x0QYxKjRYN9j connection-properties: config.decrypttrue;config.decrypt.keyMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAM5m0W... filter: config: enabled: true这段配置的含义是开启ConfigFilter过滤器声明需要解密同时把公钥传给过滤器。启动时Druid会自动读取password字段的密文用公钥解密后去数据库建连接。如果你的Druid版本较老可能不支持filter.config.enabled可以在启动参数或配置类里显式加上configFilter。手动配置方式的代码模板稍后给出。3.3 若依框架中的配置步骤若依框架RuoYi底层是Spring BootDruid的数据源配置通常在application-druid.yml文件中核心内容大致是spring: datasource: type: com.alibaba.druid.pool.DruidDataSource druid: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/ry-vue?useUnicodetruecharacterEncodingutf8 username: root password: 这里是明文密码 # 其他连接池参数 initialSize: 5 minIdle: 5 maxActive: 20 stat-view-servlet: # 监控页面相关配置要在若依框架中集成Druid密码加密操作步骤其实是替换password字段、增加config.decrypt相关配置并确认ConfigFilter生效。具体三步第一步在项目的pom.xml中确认Druid依赖存在版本建议不低于1.1.10因为低版本的ConfigTools和ConfigFilter在解密逻辑上有一些兼容问题。第二步用上面提到的ConfigTools生成密文和公钥。这一步的环境要求是JDK版本稳定遇到过某些JDK 8小版本下ConfigTools生成密钥时有Illegal key size报错的情况那是JCE无限制权限策略没装的原因换成标准JDK 8或JDK 11通常就好了。第三步修改application-druid.ymlspring: datasource: druid: username: root password: jYb1x0QYxKjRYN9j connection-properties: config.decrypttrue;config.decrypt.keyMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAM5m0W... filter: config: enabled: true如果你用的若依版本里已经定义了DruidConfig配置类并且这个配置类用ConfigurationProperties绑定了spring.datasource.druid前缀那上面的filter.config.enabled配置会自动加载不需要额外写代码。但有些自定义程度高的项目直接改成配置方式可能不生效。更稳妥的做法是在配置类里手动挂上ConfigFilterConfiguration public class DruidConfig { Bean public DruidDataSource dataSource() throws SQLException { DruidDataSource dataSource new DruidDataSource(); dataSource.setUrl(jdbc:mysql://localhost:3306/ry-vue?useUnicodetruecharacterEncodingutf8); dataSource.setUsername(root); dataSource.setPassword(jYb1x0QYxKjRYN9j); Properties properties new Properties(); // 公钥通过配置传入实际开发中建议放到环境变量或配置中心 String publicKey MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAM5m0W...; properties.setProperty(config.decrypt, true); properties.setProperty(config.decrypt.key, publicKey); dataSource.setConnectProperties(properties); ConfigFilter configFilter new ConfigFilter(); dataSource.setProxyFilters(Collections.singletonList(configFilter)); return dataSource; } }这里有个容易踩坑的点dataSource.setProxyFilters会覆盖Druid默认加载的stat、wall等监控过滤器。如果你同时还需要SQL监控和防火墙要注意把StatFilter、WallFilter也一并加进去否则监控页面会失明。正确做法是这样ListFilter filters new ArrayList(); filters.add(new ConfigFilter()); filters.add(new StatFilter()); WallFilter wallFilter new WallFilter(); wallFilter.setConfig(new WallConfig()); filters.add(wallFilter); dataSource.setProxyFilters(filters);补充一个我个人比较推荐的思路如果项目使用了druid-spring-boot-starter配置解密的优先级是spring.datasource.druid.filter.config.enabledtrue这种方式最省事它自动把ConfigFilter注入到Filter链里不用手动干预。但前提是项目中不要同时存在自定义的DruidDataSource配置类否则两边配置会打架。3.4 加密后启动报错的排查方法密码加密改造后启动报错是非常常见的情况错误类型基本分为三类我逐个说。第一类config.decrypt.key未配置或者配置错误会报ConfigFilter相关异常提示无法解密密码。这个错误信息通常比较明显去application-druid.yml检查公钥是否复制完整、有没有前后空格。复制公钥时我最怕的是行尾换行建议粘贴后人工确认一行没有多出空白字符。第二类公钥和密文不匹配。这种情况一般是改了密码后重新生成了密钥但配置里还是旧的密文或旧的公钥。我建议把生成密文-粘贴配置文件-启动验证做成一个固定流程每次换密码都走完整流程不要只替换password字段忘了更新公钥。第三类filter.config.enabled没有生效。表现为配置文件都写对了程序也没报错但启动后连不上数据库日志里显示的仍然是密文。这时要检查Druid的版本和是否真的走了ConfigFilter。简单排查方法是启动时加一行日志log.info(Druid filter classes: {}, dataSource.getProxyFilters());或者直接把password设置的值打出来看看是不是密文如果是密文且没解密说明Filter链里没有ConfigFilter。上面提到的手动挂载方式就是针对这种情况的兜底方案。另外记住一条安全红线密文和公钥不要放在同一个文件里提交到代码仓库。公钥可以放到Nacos配置中心、环境变量或部署机器上的独立配置文件中密文放在仓库里问题不大因为光有密文没有公钥解不开。这点在若依这类单体项目里执行起来可能麻烦一些但至少不要把私钥留在任何能被别人看到的地方。4. Druid监控页面从入门到实用4.1 如何正确开启监控页面Druid连接池自带一个Web监控页面路径默认是/druid/index.html。很多人知道能开但配置得一知半解开完之后要么访问不了要么裸奔在公网上没有登录保护。下面这份配置是生产可用的spring: datasource: druid: stat-view-servlet: enabled: true url-pattern: /druid/* # 登录监控页面的账号密码 login-username: monitor login-password: Monitor2024 # 允许访问的IP生产环境建议只允许内网或跳板机访问 allow: 127.0.0.1,10.0.0.0/8 deny: 0.0.0.0 # 是否允许重置监控数据生产环境必须关闭 reset-enable: false web-stat-filter: enabled: true url-pattern: /* exclusions: /druid/*,*.js,*.css,*.gif,*.jpg,*.png,*.ico session-stat-enable: true几个关键点url-pattern决定了监控页面的访问路径。有些人配成/druid/*后访问404多半是项目里还加了Shiro或Spring Security的过滤器把/druid/*拦截了。要记得在安全配置里放行这个路径。login-username和login-password是监控页面的登录凭证。密码不要太简单监控页面暴露了数据源的信息如果被公网扫到等于把家底亮给别人。allow和deny是IP白名单和黑名单。生产环境只允许运维网段访问开发环境可以本地回环。reset-enable如果开了任何人都能在页面上点击重置把SQL监控统计清零这个对排障干扰很大。一定要设为false。如果你用的是druid-spring-boot-starter上面的配置直接生效。如果是原生Druid依赖需要自己在ServletRegistrationBean和FilterRegistrationBean里注册Bean public ServletRegistrationBeanStatViewServlet druidStatViewServlet() { ServletRegistrationBeanStatViewServlet registrationBean new ServletRegistrationBean(new StatViewServlet()); registrationBean.addUrlMappings(/druid/*); registrationBean.addInitParameter(loginUsername, monitor); registrationBean.addInitParameter(loginPassword, Monitor2024); registrationBean.addInitParameter(resetEnable, false); return registrationBean; } Bean public FilterRegistrationBeanWebStatFilter druidWebStatFilter() { FilterRegistrationBeanWebStatFilter registrationBean new FilterRegistrationBean(new WebStatFilter()); registrationBean.addUrlPatterns(/*); registrationBean.addInitParameter(exclusions, /druid/*,*.js,*.css,*.gif,*.jpg,*.png,*.ico); return registrationBean; }4.2 监控指标到底怎么看监控页面打开后一般有数据源、SQL监控、SQL防火墙、Web应用、Session监控、Spring监控等几个页签。对排查连接池问题来说重点看数据源和SQL监控。数据源页签中几个指标对应的含义ActiveCount当前活跃连接数。如果不为0且持续波动代表有业务在用如果长期等于maxActive基本可以判定池子被占满。PoolingCount池中空闲连接数。这个数太低说明新请求都会走创建连接或者等待的路径。WaitThreadCount等待获取连接的线程数。这个值持续增长是连接不足的强信号。LogicConnectCount累计逻辑连接次数对应代码里getConnection()的调用次数。LogicCloseCount累计逻辑关闭次数。如果LogicCloseCount明显小于LogicConnectCount差值就是泄漏的连接数量。这是判断连接泄漏最硬的指标。RemoveAbandonedCount被Druid强制回收的连接数。这个值不为0时要么是泄漏了连接被兜底要么是长SQL被误杀。SQL监控页签中重点看这些字段ExecuteCountSQL累计执行次数。TotalTimeSQL累计总耗时。如果总耗时高、执行次数少肯定有慢SQL。MaxTimes单条SQL最大耗时能具体定位到最慢的一次执行。ErrorCountSQL执行错误次数。出现突发增长意味着数据库或者SQL逻辑出问题了。ConcurrentMax单条SQL的最大并发执行数能看出是否有热点SQL打爆数据库。实操建议监控页面不要只在出故障时才看平时要积累基线数据。比如每天早上看一眼TotalTime排名靠前的SQL稳定运行时的各项指标记录下来。没有基线故障时你根本不知道异常到底有多异常。4.3 慢SQL与防火墙的联动配置Druid的监控页面能记录慢SQL但默认没打开慢SQL统计开关。想看到哪条SQL超过多少毫秒被标记为慢查询需要在Filter配置里打开spring: datasource: druid: filter: stat: enabled: true slow-sql-millis: 1000 log-slow-sql: true打开后SQL监控页签中会单独把超过1000毫秒的SQL标出来。同时应用日志里会打印慢SQL内容方便直接定位到具体Mapper方法。不要觉得慢SQL监控只是给DBA看的。结合上面提到的慢SQL占坑场景慢SQL监控其实是连接池稳定性的第一道防线。一条慢SQL平时没啥但业务高峰期出现几十次慢执行连接池立刻告急。Druid还提供了一个很有用的功能SQL防火墙WallFilter。它是基于白名单机制去识别SQL的能拦截常见的SQL注入、批量删除、无where条件的更新删除等危险操作。spring: datasource: druid: filter: wall: enabled: true config: delete-where-none-check: true multi-statement-allow: false配置说明delete-where-none-check设为true后拦截不带where条件的delete语句防止手滑或者被注入导致全表数据被清空。multi-statement-allow设为false禁止一次执行多条SQL这个能防御部分注入攻击。insert-value-check、dml-statement-check等选项可以根据团队规范再开。注意一点防火墙和监控是两套独立的Filter。开了WallFilter后如果SQL被拦截监控页面的SQL防火墙页签里会出现拦截记录。平时看到拦截记录不用紧张重点看拦截原因和对应SQL是谁发出来的。我就遇到过测试环境有人手工在数据库客户端扫库防火墙不断拦截并记录虽然没造成问题但暴露了开发环境的访问控制有漏洞。5. 常见问题排查速查表5.1 典型故障与解决对照表我把这么多年遇到的高频Druid问题整理成一张对照表方便你直接按图索骥排查。故障现象可能原因排查动作解决方案连接获取超时active顶满maxActive连接泄漏或慢SQL占坑查监控页面的LogicConnectCount与LogicCloseCount差值看SQL监控的慢查询列表修泄漏代码加索引优化慢SQL必要时临时调大maxActive日志报错wait millis 5000, active 20, maxActive 20并发突增超过连接池上限看WaitThreadCount和SQL监控执行频率压测后合理调大maxActive或引入读写分离分摊压力连接有效但执行时报Closed connectiontestOnBorrow为true导致坏连接没被及时剔除后又返回给上层看错误堆栈是否卡在校验SQL阶段改testWhileIdle配合validationQuery配置timeBetweenEvictionRunsMillis连接池状态健康但请求依旧变慢数据库连接数被打满连接池等待或新建连接频繁登数据库看show processlist优化慢SQL限制应用最大连接数排查第三方连接占用Druid监控页面打不开安全框架拦截了/druid/路径检查Shiro、Spring Security的过滤规则看是否有过滤器把请求拦截了放行/druid/路径同时限制IP白名单SQL监控没有数据StatFilter未开启或filter顺序被覆盖看filter.stat.enabled是否为true检查自定义Filter列表恢复StatFilter到Filter链中密码加密后应用启动失败公钥或密文配置错误ConfigFilter未挂载打印dataSource.getProxyFilters()检查Filter列表核对公钥密文重新走生成流程手动添加ConfigFilter5.2 几个避免线上踩坑的小建议很多连接池问题不是一次性爆发的而是慢慢积累等到某个高峰时刻才集中引爆。所以给几条长期收益很高的习惯第一线上环境开启慢SQL监控并把慢SQL告警接入企业微信、钉钉群。不要等用户报障了再去翻监控慢SQL告警是连接池问题的前兆信号。Druid的log-slow-sql方案搭配日志采集就能做成本极低。第二不要把removeAbandoned当作连接泄漏的常规解药。Druid设计这个参数是为了兜底不是让你放着不管泄漏代码。我的建议是先通过监控页面的LogicConnectCount - LogicCloseCount差值确认泄漏存在再通过getActiveConnectionStackTrace()定位代码位置修掉它最后才打开removeAbandoned作为保底。第三若依框架或其它基于Spring Boot的项目升级Druid版本要慎重。版本升级带来的意外不一定是连接池本身的问题而可能是和MyBatis、MyBatis Plus、Spring Boot Actuator的兼容性问题。升级前先看Druid的release notes升级后压测一下连接池的获取连接延迟和SQL监控数据确认没有异常再全量发布。第四密码加密是一次性投入、长期受益的事。很多人嫌麻烦一直拖其实从生成密钥到改配置熟练之后十分钟就能搞定。这个改造还能顺便满足等保测评对敏感配置项的要求性价比很高。最后说点个人体会踩过这次Druid的坑之后我对连接池的认知有了很大变化。连接池不是配好之后就一劳永逸的组件它更像是一个透明的水箱——你看得见水位监控数据但看不见管道哪里在漏水连接泄漏只有出事了才能顺着痕迹摸到源头。所以我现在的习惯是每个月至少人工巡检一次Druid监控页面专门看LogicConnectCount和LogicCloseCount的差值走向同时把慢SQL的阈值从默认调小让问题暴露在早期而不是爆发在深夜。还有一个在实践经验里验证过多次的小技巧遇到连接池问题第一时间用jstack抓线程快照然后用jcmd或者arthas去执行getActiveConnectionStackTrace()把Druid里那些活跃连接归到对应的业务线程上基本能在十分钟内锁定是哪段代码没有归还连接。这套方法在排查连接泄漏和慢SQL占坑这两类问题上成功率非常高。如果你现在正准备给项目接Druid或者已经在用但想加固一下优先做三件事把密码加密开起来把监控页面配置好把慢SQL阈值调到合适的大小。这三件事做完Druid才算真正用起来而不是只是换了个连接池的名字。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门