首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Tomcat 數據庫連接池配置全攻略:JNDI + Spring 兩種模式最佳實踐

     編輯:Java 相關知識

前言

數據庫連接池是 Web 應用性能的關鍵基礎設施。本文詳細講解 Tomcat 容器級連接池配置(JNDI 模式)、Web 應用引用方式,以及 Spring 框架整合兩大主流模式,附帶生產環境調優參數與避坑指南。

一、為什麼需要連接池?

無連接池有連接池
每請求創建/銷毀連接,極其消耗資源與時間預創建連接池,請求借用/歸還,毫秒級獲取
高併發下數據庫連接數失控,導致拒絕服務最大連接數可控,防雪崩
連接洩漏難排查統一生命週期管理,監控指標豐富

二、Tomcat 容器級配置(JNDI 模式)

1. context.xml 配置

路徑:$CATALINA_BASE/conf/context.xml 或項目 META-INF/context.xml


<Context>
    <!-- SQL Server 示例 -->
    <Resource name="jdbc/news"
              auth="Container"
              type="javax.sql.DataSource"
              maxTotal="100"
              maxIdle="30"
              maxWaitMillis="10000"
              username="sa"
              password="120010"
              driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
              url="jdbc:sqlserver://localhost:1433;DatabaseName=news"
              validationQuery="SELECT 1"
              testOnBorrow="true"
              testWhileIdle="true"
              timeBetweenEvictionRunsMillis="60000"
              minEvictableIdleTimeMillis="300000"
              removeAbandonedOnBorrow="true"
              removeAbandonedTimeout="60"
              logAbandoned="true" />

    <!-- Oracle 示例 -->
    <Resource name="jdbc/oracle"
              auth="Container"
              type="javax.sql.DataSource"
              maxTotal="100"
              maxIdle="30"
              maxWaitMillis="10000"
              username="test"
              password="bg"
              driverClassName="oracle.jdbc.driver.OracleDriver"
              url="jdbc:oracle:thin:@192.168.2.102:1521:orcl"
              validationQuery="SELECT 1 FROM DUAL"
              testOnBorrow="true" />
</Context>

2. 關鍵參數詳解

參數含義建議值
maxTotal最大活躍連接數100-200(視 DB 最大連接數與應用並發)
maxIdle最大空閒連接數30-50
maxWaitMillis獲取連接最大等待毫秒數10000(10秒)
validationQuery驗證連接有效性的 SQLMySQL: SELECT 1; Oracle: SELECT 1 FROM DUAL; SQL Server: SELECT 1
testOnBorrow借用時驗證true(性能微損,換取穩定)
testWhileIdle空閒驗證true
timeBetweenEvictionRunsMillis空閒驗證間隔60000(1分鐘)
minEvictableIdleTimeMillis最小空閒驅逐時間300000(5分鐘)
removeAbandonedOnBorrow借用時回收棄用連接true(防洩漏)
removeAbandonedTimeout棄用判定秒數60-300
logAbandoned記錄棄用堆棧true(排查洩漏)

3. 驅動包部署

  • 將 JDBC 驅動 JAR(如 mssql-jdbc.jar, ojdbc8.jar)放入 $CATALINA_HOME/lib/
  • 不要 放在項目 WEB-INF/lib/,否則類加載器隔離導致 ClassNotFoundException

三、Web 應用引用 JNDI 數據源

1. web.xml 聲明引用


<resource-ref>
    <res-ref-name>jdbc/news</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

res-ref-name 必須與 context.xml 中 name 一致(不含 jdbc/ 前綴也可,視容器實現)。

2. 代碼中查找使用


import javax.naming.*;
import javax.sql.DataSource;
import java.sql.Connection;

public class Dao {
    private DataSource dataSource;

    public Dao() throws NamingException {
        Context ctx = new InitialContext();
        // 標準 JNDI 名稱:java:comp/env/ + res-ref-name
        dataSource = (DataSource) ctx.lookup("java:comp/env/jdbc/news");
    }

    public int countUsers() {
        String sql = "SELECT COUNT(*) FROM users";
        try (Connection conn = dataSource.getConnection()) {
            return conn.createStatement().executeQuery(sql).getInt(1);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

四、Spring 整合模式

模式一:Spring 管理 JNDI 查找(推薦)


<!-- applicationContext.xml -->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/jdbc/news" />
    <property name="proxyInterface" value="javax.sql.DataSource" />
    <property name="lookupOnStartup" value="true" />
    <property name="cache" value="true" />
    <property name="resourceRef" value="true" /> <!-- 自動補全 java:comp/env/ -->
</bean>

<!-- 事務管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

模式二:Spring 直接配置連接池(無容器依賴,適合測試/微服務)


<!-- 使用 HikariCP(Spring Boot 2+ 默認) -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
    <property name="jdbcUrl" value="jdbc:sqlserver://localhost:1433;DatabaseName=news" />
    <property name="username" value="sa" />
    <property name="password" value="120010" />
    <property name="maximumPoolSize" value="100" />
    <property name="minimumIdle" value="10" />
    <property name="idleTimeout" value="300000" />
    <property name="maxLifetime" value="1800000" />
    <property name="connectionTimeout" value="10000" />
    <property name="connectionTestQuery" value="SELECT 1" />
    <property name="poolName" value="HikariPool-App" />
</bean>

模式三:Spring Boot 自動配置(application.yml)


spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
    url: jdbc:sqlserver://localhost:1433;DatabaseName=news
    username: sa
    password: 120010
    hikari:
      maximum-pool-size: 100
      minimum-idle: 10
      idle-timeout: 300000
      max-lifetime: 1800000
      connection-timeout: 10000
      connection-test-query: SELECT 1
      pool-name: HikariPool-App
  jndi-name: java:comp/env/jdbc/news  # 若部署至 Tomcat 且啟用 JNDI

五、生產環境最佳實踐清單

  1. 驅動包隔離:Tomcat lib 目錄放驅動,項目不打包驅動
  2. 連接驗證:testOnBorrow=true + validationQuery,防斷連
  3. 洩漏檢測:removeAbandonedOnBorrow=true + logAbandoned=true
  4. 監控指標:暴露 numActive, numIdle, numWaiting 到 Prometheus/Grafana
  5. 容量規劃:maxTotal ≤ DB max_connections - 預留,多應用共享 DB 需協調
  6. 超時設置:maxWaitMillis 略大於業務最大容忍延遲
  7. 優雅關閉:Spring destroy-method="close" / Hikari close() 確保連接歸還
  8. 避免長事務:業務邏輯與事務邊界分離,連接歸還不等於事務提交

六、常見故障排查

現象可能原因排查命令/日誌
獲取連接超時池耗盡/洩漏/DB 繁忙jmx 查看 numActive/numIdle、日誌搜尋 "abandoned"
Communications link failure連接被防火牆/DB 斷開驗證 query + testWhileIdle + 減少 idleTimeout
ClassNotFoundException: Driver驅動包未放 Tomcat lib檢查 $CATALINA_HOME/lib/
JNDI NameNotFoundExceptionresource-ref 名稱不匹配對比 web.xml res-ref-name 與 context.xml name

七、總結

Tomcat 連接池配置核心三步:

  1. context.xml 定義 Resource(驅動、URL、池參數、驗證策略)
  2. web.xml 聲明 resource-ref(應用與容器解耦)
  3. 代碼/Spring 通過 java:comp/env/xxx 查找使用

生產環境強烈建議:容器級池 + Spring JNDI 查找 或 Spring Boot + HikariCP 兩條成熟路徑。理解每個參數的業務含義,建立監控告警體系,才能在高併發下守住數據庫穩定性底線。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved