1. 项目概述为什么我们需要Druid监控页面在任何一个稍微有点规模的Java应用里数据库连接池都是那个默默无闻但又至关重要的“心脏”。它负责管理应用与数据库之间的连接连接的创建、销毁、复用都直接影响着应用的响应速度和稳定性。我见过太多线上事故追根溯源最后发现是连接池配置不当连接泄漏导致数据库连接数耗尽应用彻底瘫痪或者慢SQL堆积拖垮整个数据库实例。这时候光看应用日志是没用的你需要一双能直接透视连接池内部运行状态的眼睛。这就是Druid监控页面的价值所在。Druid不仅仅是阿里巴巴开源的一个高性能数据库连接池它更是一个自带强大监控能力的“瑞士军刀”。其内置的监控页面StatViewServlet提供了一个Web可视化界面让你能实时、直观地看到连接池的每一个关键指标活跃连接数、等待线程数、执行SQL的统计、慢SQL清单等等。这比在代码里打日志或者依赖第三方复杂的APM工具要直接得多。对于开发者和运维来说配置好这个监控页面就等于在数据库访问这个关键路径上装了一个高清摄像头任何风吹草动都尽在掌握。今天我就结合自己多年在项目中的实战经验从零开始带你彻底搞懂Druid监控页面的配置、使用以及那些官方文档里不会写的“坑”。无论你是刚接触Druid的新手还是想优化现有监控的老手这篇文章都能给你提供可直接落地的方案。2. Druid监控页面的核心配置详解配置Druid监控页面本质上是在Web应用中注册一个特殊的ServletStatViewServlet和一个FilterWebStatFilter。这个过程并不复杂但里面的每一个参数都关乎监控的准确性、安全性和性能。下面我们分Spring Boot和传统Servlet两种环境来详细拆解。2.1 基于Spring Boot的配置推荐Spring Boot的自动配置让事情变得简单但我们通常需要一些自定义配置来满足生产环境的要求。主要涉及application.yml或application.properties和可能的配置类。2.1.1 基础YAML配置与参数解析首先在pom.xml中确保引入了Druid Spring Boot Starter依赖。dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.20/version !-- 请使用最新稳定版本 -- /dependency然后在application.yml中进行核心配置spring: datasource: type: com.alibaba.druid.pool.DruidDataSource druid: # 1. 数据库连接基本配置 url: jdbc:mysql://localhost:3306/your_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: your_username password: your_password driver-class-name: com.mysql.cj.jdbc.Driver # 2. 连接池核心参数配置监控数据的基础 initial-size: 5 min-idle: 5 max-active: 20 max-wait: 60000 # 获取连接超时时间单位毫秒 test-on-borrow: false # 不建议开启性能差 test-on-return: false test-while-idle: true # 必须开启依靠空闲连接检测 validation-query: SELECT 1 time-between-eviction-runs-millis: 60000 # 空闲连接检测周期 min-evictable-idle-time-millis: 300000 # 连接最小空闲时间 # 3. 监控页面StatViewServlet配置 stat-view-servlet: enabled: true # 开启内置监控页面 url-pattern: /druid/* # 访问路径可自定义 reset-enable: false # 生产环境务必关闭否则可以通过页面重置所有数据 login-username: admin # 监控页登录用户名生产环境必须设置 login-password: admin123 # 监控页登录密码 allow: 192.168.1.100, 127.0.0.1 # 白名单不配置或为空则允许所有访问危险 deny: 192.168.1.73 # 黑名单优先级高于allow # 4. Web关联监控WebStatFilter配置 web-stat-filter: enabled: true # 开启Web应用监控 url-pattern: /* # 过滤所有URL exclusions: *.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/* # 排除静态资源和监控页面本身 session-stat-enable: true # 开启session统计 session-stat-max-count: 1000 # session最多统计个数 # 5. SQL监控与防火墙配置 filter: stat: enabled: true # 开启SQL监控 log-slow-sql: true # 记录慢SQL slow-sql-millis: 2000 # 慢SQL阈值单位毫秒 merge-sql: true # 合并相似的SQL便于统计 wall: enabled: true # 开启SQL防火墙防御SQL注入 config: drop-table-allow: false # 禁止删表语句关键参数解读与避坑指南reset-enable: false这是血泪教训。曾经有测试同学误点了监控页面的“重置”按钮导致线上运行了几周的监控数据瞬间清零无法追溯历史问题。生产环境一定要关闭。login-username/password和allow/deny监控页面会暴露数据库连接数、SQL语句等敏感信息。绝对不要在公网环境不设密码和IP限制。allow支持IP和子网掩码格式如192.168.1.0/24。test-while-idle与validation-query这是保证连接有效性的黄金组合。通过定期检查空闲连接及时剔除失效连接避免应用拿到已断开的数据库连接报错。slow-sql-millis这个值需要根据你的业务数据库性能来定。对于OLTP业务1-2秒可能就算慢了对于报表类查询5-10秒也可能可以接受。设置后慢SQL会在监控页的“SQL监控”和“慢SQL”标签页高亮显示。2.1.2 通过Java Config进行高级定制如果YAML配置不能满足你的需求比如需要更复杂的Filter链或者要集成到自定义的登录认证体系中你可以使用Configuration类。Configuration public class DruidConfig { /** * 自定义StatViewServlet配置。 * 通常用YAML配置就够了这里演示如何添加自定义初始化参数。 */ Bean public ServletRegistrationBeanStatViewServlet statViewServlet() { ServletRegistrationBeanStatViewServlet registrationBean new ServletRegistrationBean(new StatViewServlet(), /druid/*); // 添加初始化参数 MapString, String initParams new HashMap(); initParams.put(loginUsername, admin); initParams.put(loginPassword, admin123); initParams.put(resetEnable, false); // 添加一个自定义参数比如页面标题 initParams.put(sysTitle, 我的业务系统监控中心); registrationBean.setInitParameters(initParams); return registrationBean; } /** * 自定义WebStatFilter配置。 * 可以更精细地控制需要统计的URL和Session。 */ Bean public FilterRegistrationBeanWebStatFilter webStatFilter() { FilterRegistrationBeanWebStatFilter registrationBean new FilterRegistrationBean(new WebStatFilter()); registrationBean.setUrlPatterns(Arrays.asList(/*)); MapString, String initParams new HashMap(); initParams.put(exclusions, *.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*); // 开启Profile可以查看调用栈对性能有轻微影响调试时开启 initParams.put(profileEnable, true); registrationBean.setInitParameters(initParams); return registrationBean; } /** * 自定义Druid数据源配置覆盖自动配置的属性。 * 这里可以注入在YAML中配置的spring.datasource.druid下的属性。 */ ConfigurationProperties(spring.datasource.druid) Bean(initMethod init, destroyMethod close) public DataSource dataSource() throws SQLException { // 此处会读取YAML配置同时可以在这里进行编程式覆盖 DruidDataSource datasource new DruidDataSource(); // 手动添加Filter比如添加日志Filter将SQL输出到日志文件 ListFilter filters new ArrayList(); filters.add(new Slf4jLogFilter()); // 需要log4j或logback支持 datasource.setProxyFilters(filters); return datasource; } }实操心得在99%的场景下使用YAML配置已经完全足够且更清晰。只有当你需要实现一些非常特定的行为比如动态修改监控页面参数、集成公司统一的权限框架时才需要动用Java Config。过度定制会增加维护复杂度。2.2 传统Servlet/WEB项目的配置对于非Spring Boot的Web项目如使用纯Servlet、Spring MVC非Boot方式需要在web.xml中进行配置。?xml version1.0 encodingUTF-8? web-app ... !-- 1. 配置Druid数据源 (通常通过Spring或其它方式注入这里省略) -- !-- 2. 配置监控页面 Servlet -- servlet servlet-nameDruidStatView/servlet-name servlet-classcom.alibaba.druid.support.http.StatViewServlet/servlet-class init-param param-nameloginUsername/param-name param-valueadmin/param-value /init-param init-param param-nameloginPassword/param-name param-valueadmin123/param-value /init-param init-param param-nameresetEnable/param-name param-valuefalse/param-value /init-param /servlet servlet-mapping servlet-nameDruidStatView/servlet-name url-pattern/druid/*/url-pattern /servlet-mapping !-- 3. 配置Web统计 Filter -- filter filter-nameDruidWebStatFilter/filter-name filter-classcom.alibaba.druid.support.http.WebStatFilter/filter-class init-param param-nameexclusions/param-name param-value*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*/param-value /init-param init-param param-namesessionStatEnable/param-name param-valuetrue/param-value /init-param /filter filter-mapping filter-nameDruidWebStatFilter/filter-name url-pattern/*/url-pattern /filter-mapping /web-app注意事项传统项目配置相对繁琐且数据源需要手动初始化并设置到Filter和Servlet中通过DruidStatManagerFacade步骤更多容易出错。这也是为什么Spring Boot方案更受欢迎的原因。3. 监控页面功能全景与实战解读配置完成后启动你的应用访问http://你的应用地址/druid/index.html输入配置的用户名密码即可进入Druid监控主页面。这个页面信息量巨大我们把它拆解成几个核心板块来看。3.1 数据源概览连接池的健康仪表盘这是首页的核心区域展示连接池的实时运行状态。关键指标含义解读健康状态参考值异常排查思路初始化连接数连接池启动时创建的连接数量。等于initial-size配置值。启动后不为配置值检查配置是否生效。最小空闲连接连接池中始终保持的最小空闲连接数。等于min-idle配置值。长期远大于此值可能max-active设置过大或流量低。最大活跃连接连接池能同时维持的最大连接数。等于max-active配置值。核心指标接近或等于此值说明连接池已满。当前活跃连接正在被业务使用的连接数。应远小于max-active且波动平稳。持续高位或达到max-active可能存在连接泄漏或慢SQL。池中空闲连接创建好但未被使用的连接数。应在min-idle附近波动。长期为0可能min-idle设置过小或max-active不足。等待线程数在getConnection()时因无可用连接而进入等待的线程数。理想状态应为0。持续大于0是连接池瓶颈的明确信号需立即扩容或优化。SQL执行总数自启动以来执行的SQL总数。-结合QPS看趋势。事务总数自启动以来开启的事务数。--连接持有时间分布统计连接从被取用到归还的时间段分布。大部分连接应在“0-1ms”或“1-10ms”区间。如果“1s”区间占比较高说明存在长事务或慢查询占用连接。实战场景分析假设你看到“当前活跃连接”一直维持在max-active比如20个“等待线程数”有5个。这几乎可以肯定发生了连接泄漏。你的排查步骤应该是立即去“SQL”或“慢SQL”页面按“执行时长”排序找出最耗时的SQL。检查这些SQL是否没有正确关闭Connection、Statement或ResultSet。Druid的“连接泄漏检测”功能需额外开启可以帮助定位。如果慢SQL不多则可能是业务代码在事务中进行了长时间处理如循环、远程调用导致连接占用过久。3.2 SQL监控与慢SQL清单定位性能瓶颈的利器这是Druid监控最强大的功能之一。它记录了每一条执行过的SQL的详细数据。3.2.1 SQL监控页面解读进入“SQL监控”页你会看到一个表格包含以下关键列SQL执行的具体SQL语句merge-sql开启后参数会被?替换相同模式的SQL被合并统计。执行数该SQL被执行的次数。执行时间该SQL总耗时。最慢、平均(ms)、并发性能核心指标。读取行数、更新行数反映了SQL的数据影响范围。执行RsHold执行时间结果集持有时间。这个值如果远大于“执行时间”说明程序从数据库取回数据后在内存中处理了很长时间才关闭结果集这也是变相的资源占用3.2.2 慢SQL页面深度利用“慢SQL”页面专门展示超过slow-sql-millis阈值的SQL。这里不仅是看个列表更要会分析。关联上下文点击某条慢SQL的“SQL”内容可以查看其详细的执行时间分布直方图。结合“最近一段时间”的筛选可以判断这个慢SQL是突然出现还是历史顽疾。对比分析将“平均耗时”最高的几条SQL与“执行次数”最高的几条SQL进行对比。有时一个执行很快但调用量巨大的SQL其总消耗资源可能超过一个很慢但调用量小的SQL。采样详情Druid会记录慢SQL的样本通过connectionProperties配置druid.stat.logSlowSqltrue;druid.stat.slowSqlMillis2000你可以看到具体的参数值和执行时间这对于调试因特定参数导致的慢查询至关重要。独家技巧如何将慢SQL告警接入监控系统Druid监控页面本身没有告警功能。我的做法是定期如每分钟通过一个健康检查接口集成DruidStatManagerFacade或直接读取Druid提供的JSON API/druid/webapp.json或/druid/sql.json来获取慢SQL列表。然后写一个简单的脚本如果慢SQL列表不为空或者某个SQL的平均执行时间超过动态阈值就触发公司的告警平台如钉钉、企业微信、Prometheus Alertmanager。这样就把Druid的监控能力从“被动查看”升级到了“主动告警”。3.3 Web应用监控与URI监控这个模块由WebStatFilter提供它将Web请求与数据库访问关联起来。URL监控统计每个Web接口URI的请求次数、并发、耗时以及该请求执行了多少次SQL。这是一个黄金功能。你可以立刻发现哪个API是“数据库杀手”。比如一个查询用户详情的API平均一次请求执行了50条SQL这很可能遇到了N1查询问题在ORM框架如MyBatis、JPA中常见。Session监控查看在线用户Session情况。Spring监控需额外配置如果你集成了Druid的Spring监控还可以看到Spring Bean的方法调用统计进一步细化性能热点。配置Spring监控以Spring Boot为例在配置类中增加一个BeanBean public ServletRegistrationBeanStatViewServlet statViewServlet() { // ... 同上 ... // 添加支持Spring监控的参数 initParams.put(spring.datasource.druid.stat-view-servlet.profileEnable, true); // 在WebStatFilter里也要开 // 或者更推荐的方式在YAML中配置 druid.web-stat-filter.profile-enable: true return registrationBean; } // 还需要在pom.xml中添加AOP依赖如果还没有的话 // dependency // groupIdorg.springframework.boot/groupId // artifactIdspring-boot-starter-aop/artifactId // /dependency配置后“Web应用”模块下会出现“Spring”子页面展示Bean方法的执行情况。4. 生产环境高级调优与安全加固基础配置只能保证监控页面跑起来要让它真正在生产环境稳定、安全、高效地发挥作用还需要做以下几件事。4.1 性能调优不让监控本身成为负担Druid监控在记录SQL和Web请求时会有一定的性能开销主要是CPU和内存。对于超高并发的应用需要精细调整。调整采样率与合并SQLspring: datasource: druid: filter: stat: enabled: true merge-sql: true # 必须开启大幅减少内存占用 slow-sql-millis: 1000 log-slow-sql: true # 关键参数设置SQL执行时间的日志输出阈值避免全量记录 # 只有执行时间超过此值的SQL才会被记录到日志文件如果配置了LogFilter connection-properties: druid.stat.slowSqlMillis1000;druid.stat.logSlowSqltrue通过merge-sql合并相同模式的SQL能极大减少内存中维护的监控数据项。控制监控数据的内存占用Druid的监控数据默认保存在内存中。长时间运行后如果SQL种类极多可能占用不小内存。可以通过DruidDataSource的setRemoveAbandoned等相关参数来清理不再使用的监控数据但更常见的做法是定期重启应用实例在微服务架构下很自然或者只关注最近一段时间如1小时的数据。谨慎开启ProfileprofileEnable参数会记录调用栈用于定位执行SQL的代码位置但开销较大。建议只在预发环境或排查具体问题时临时开启。4.2 安全加固锁好你的“监控后门”监控页面泄露的危害不亚于源码泄露。必须严防死守。强制访问控制最重要如前所述必须设置login-username、login-password以及allowIP白名单。生产环境的白名单通常只允许运维网络跳板机或监控服务器IP访问。使用内网域名或路径隐藏不要使用显而易见的/druid路径可以改为一个无规律的字符串。同时确保该服务只在内网暴露或通过网关/反向代理如Nginx增加一层HTTP Basic认证或集成公司单点登录。禁用重置功能再次强调reset-enable: false。定期审计访问日志检查是否有异常IP尝试访问监控页面。4.3 与现有监控体系集成大公司通常有统一的监控平台如Prometheus Grafana。我们可以将Druid的指标暴露出去。使用Spring Boot Actuator集成Druid Spring Boot Starter已经提供了对Actuator的集成。添加spring-boot-starter-actuator依赖并在配置中暴露metrics端点Druid的相关指标如jdbc.connections.active会自动通过/actuator/metrics端点暴露然后被Prometheus抓取。management: endpoints: web: exposure: include: health,info,metrics,prometheus metrics: export: prometheus: enabled: true自定义Endpoint如果需要更定制化的数据如慢SQL列表可以自己写一个Spring BootEndpoint在内部调用DruidStatManagerFacade.getInstance().getSqlStatDataMap()等方法获取数据并以JSON格式返回。5. 常见问题排查与实战案例即使配置正确在实际运行中也可能遇到各种问题。这里记录几个我踩过的坑和解决方案。5.1 监控页面无法访问404可能原因1Servlet路径未正确注册。检查确认stat-view-servlet.url-pattern的配置。Spring Boot默认是/druid/*。访问时路径必须是http://host:port/context-path/druid/index.html。解决检查应用日志看Druid的Servlet是否成功启动。在Spring Boot启动日志中搜索“DruidStatViewServlet”或“druid”。可能原因2Spring Security或其它过滤器拦截。检查如果你的项目使用了Spring Security它可能会拦截/druid/*路径。解决在Security配置中放行该路径。Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers(/druid/**).permitAll() // 放行druid监控路径 .anyRequest().authenticated() .and().formLogin(); }5.2 监控页面没有SQL数据或数据不全可能原因1Filter配置顺序问题或未生效。检查statFilter是否被正确添加。在传统web.xml中Filter顺序有影响。在Spring Boot中确保spring.datasource.druid.filter.stat.enabledtrue。解决检查数据源初始化日志确认druid-filter已加载。可以尝试在application.yml中显示指定filtersfilters: stat,wall,log4j2根据你用的日志框架。可能原因2使用了非Druid的数据源。检查确保你的应用实际使用的DataSource是DruidDataSource。有时因为依赖冲突或配置错误可能被替换成了HikariCP或Tomcat JDBC Pool。解决在应用启动后打印一下DataSource的类名System.out.println(dataSource.getClass().getName());。可能原因3多数据源配置下监控失效。场景使用dynamic-datasource-spring-boot-starter等多数据源组件时默认的Druid监控可能只监控主数据源。解决这需要为每个DruidDataSource实例单独配置并注册到同一个StatViewServlet的监控中过程较为复杂。通常的变通方案是只监控最主要的数据源或者考虑使用更全面的分布式链路追踪工具如SkyWalking。5.3 监控页面打开缓慢或影响应用性能可能原因监控数据量过大渲染耗时。检查打开浏览器开发者工具的网络面板查看加载/druid/index.html后的一系列JSON数据请求如/druid/webapp.json的响应时间。解决增加spring.datasource.druid.stat-view-servlet.session-stat-max-count默认1000等参数限制减少历史数据积累。如前文所述开启merge-sql。考虑在访问量低的时段查看监控或定期清理应用内存重启。5.4 连接泄漏Active Connections持续不降这是最经典的问题。除了在监控页观察“活跃连接数”是否在请求结束后回落还可以开启Druid的连接泄漏检测功能。spring: datasource: druid: # 开启移除长时间未关闭连接的功能 remove-abandoned: true # 连接被占用的超时时间单位秒例如300秒 remove-abandoned-timeout: 300 # 输出泄漏连接的日志和堆栈信息 log-abandoned: true开启后如果一个连接被获取后超过remove-abandoned-timeout时间仍未归还Druid会认为它泄漏了会强制回收并打印警告日志包含堆栈跟踪其中就能看到是哪个线程、哪段代码没有正确关闭连接。注意这个功能有性能开销且是最后一道防线根本解决之道还是修复代码中的资源关闭逻辑。配置并使用Druid监控页面就像是给你的数据库访问层做了一次全面的“体检”和“实时监护”。它不能直接解决性能问题但能为你提供最精准的“诊断报告”。从连接池的基本状态到每一条慢SQL的细节从Web接口的调用链到Spring方法的执行耗时这些数据是任何性能优化和故障排查的起点。我的习惯是在项目上线前一定会把Druid监控配好并且把监控页面的地址和账号密码记在团队的运维手册里。当线上出现数据库相关告警时第一个打开的往往就是这个页面。花半小时配置换来的是线上问题排查效率数倍的提升这笔投入产出比绝对是值得的。最后一个小建议定期比如每周花几分钟浏览一下监控页面的“慢SQL”和“URI监控”也许就能在用户投诉之前提前发现那些正在悄悄变慢的接口和SQL。