首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

Tomcat 效能調優全攻略:JVM、OS、連接器、集群與實戰案例

     編輯:MySQL 資料庫相關知識

調優兩大維度

  1. 外部環境:JVM 參數、作業系統、前端 Web Server 整合、負載均衡
  2. Tomcat 自身:連接器執行緒、JSP 編譯、容量規劃、會話管理

一、JVM 記憶體與 GC 調優

堆記憶體核心參數


# catalina.sh / catalina.bat 開頭加入
JAVA_OPTS="-Xms256m -Xmx512m -XX:PermSize=64m -XX:MaxPermSize=128m"
# JDK 8+ 使用 Metaspace
JAVA_OPTS="-Xms2g -Xmx2g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m"
  • -Xms:初始堆大小,建議與 -Xmx 設定相同,避免動態擴容抖動
  • -Xmx:最大堆,建議 ≤ 物理記憶體 80%,預留 OS、Metaspace、Code Cache、Thread Stack 空間

GC 策略選擇

收集器組合適用場景JDK 版本
ParNew + CMS低延遲、響應敏感型應用JDK 7/8
Parallel Scavenge + Parallel Old高吞吐、批次處理、科學計算JDK 7/8
G1GC大堆(>4GB)、可預測停頓、混合負載JDK 7u4+ / 8/9+
ZGC / Shenandoah超大堆(>16GB)、亞毫秒級停頓JDK 11+ / 12+

# CMS 範例
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC
-XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly

# G1 範例
-XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=45

GC 日誌與分析


-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/var/log/tomcat/gc.log
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M

工具:GCViewer、GCEasy.io、Arthas、JProfiler

二、作業系統層面優化

  • 檔案描述符:ulimit -n 65535(/etc/security/limits.conf)
  • TCP 參數:net.core.somaxconn=65535、net.ipv4.tcp_tw_reuse=1、net.ipv4.tcp_fin_timeout=15
  • 關閉 THP:echo never > /sys/kernel/mm/transparent_hugepage/enabled(減少 JVM 延遲尖峰)
  • NTP 時間同步:分布式系統基礎
  • Swappiness:vm.swappiness=1(避免 JVM 堆被 swap 出)

三、Tomcat 連接器調優

關閉 DNS 查詢(立竿見影)



    connectionTimeout="20000"
    redirectPort="8443" />

執行緒池尺寸規劃



    minSpareThreads="100"   
    maxSpareThreads="200"   
    acceptCount="1000"      
    connectionTimeout="20000"
    enableLookups="false" />
  • maxThreads:CPU 核心數 × (1 + 平均等待時間/平均計算時間),典型 200-800
  • acceptCount:擋住突發流量,超過拋棄連接(回傳 503)
  • 監控 ThreadPool MBean:currentThreadCount、currentThreadsBusy

NIO / APR 原生庫提升吞吐







四、前端整合:Apache / Nginx 反向代理

  • 靜態資源由 Nginx/Apache 直接服務,Tomcat 僅處理動態請求(JSP、Servlet、API)
  • 連接複用:上游保持長連接(proxy_http_version 1.1; proxy_set_header Connection "";)
  • 負載均衡演算法:Least Connections、IP Hash(Session Sticky)、Weighted Round Robin

Nginx 範例


upstream tomcat_cluster {
    least_conn;
    server 10.0.1.10:8080 weight=3 max_fails=3 fail_timeout=30s;
    server 10.0.1.11:8080 weight=2 max_fails=3 fail_timeout=30s;
    keepalive 100;
}

server {
    location /static/ { root /var/www; expires 30d; }
    location / {
        proxy_pass https://tomcat_cluster;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

五、Session 複寫與集群決策

方案優點缺點建議場景
Tomcat DeltaManager(全量廣播)配置簡單節點>3 時網路風暴、效能崩潰極小規模(2-3 節點)
BackupManager(主備)流量較小單點備份、擴展性差雙節點熱備
Redis / Memcached Session 共享水平擴展、解耦、高可用引入外部依賴、序列化開銷生產環境標準選擇
Sticky Session(IP Hash)無需同步、效能最好節點故障導致 Session 丟失可容忍短暫登出的業務

實戰教訓:某專案引入 DeltaManager 導致 CPU 飆升、GC 頻繁,最終改為 Nginx IP Hash + Redis Session 徹底解決。

六、容量規劃與壓力測試

  • 經驗式:參考同類業務 QPS、單請求記憶體、CPU 估算
  • 科學式:基準測試 + 壓力模型 + 目標 SLA(P99 < 200ms、錯誤率 < 0.1%)
  • 工具:JMeter、Gatling、wrk、Locust

七、綜合實戰案例:Apache + Tomcat + MySQL 架構優化

背景

  • 目標:3 萬在線、100 並發
  • 初始:Apache 2.0.54 + Tomcat 5.0.30 + MySQL 4.1.14 + JDK 1.5
  • 硬體:3 台 2.4GHz/1GB RAM,100M 內網

踩坑與解決

問題根因解決
Tomcat Cluster 導致極慢Session 複寫風暴、不支援 Application 複寫移除 Cluster,改 Sticky Session
Windows 2000 專業版並發限制 15作業系統連接數上限全環境升級 Windows 2003 Server
DBCP 連接池初始化只有 1 條、擴容慢JDK 1.5 JDBC 驅動相容性問題降級 JDK 1.4、改用 C3P0
DBCP 連接斷開後不重建已知 Bug遷移至 C3P0(Hibernate 3 預設)

最終調優配置摘要


# Tomcat (server.xml)



# JVM
-Xms512m -Xmx768m  (視實例權重)

# Apache (httpd.conf + workers.properties)
ThreadsPerChild 1900
MaxRequestsPerChild 10000
worker.tomcat1.lbfactor=900
worker.tomcat2.lbfactor=2000

# MySQL (my.cnf)
innodb_buffer_pool_size=1G
max_connections=1000
query_cache_size=64M

# C3P0 (Spring)
hibernate.c3p0.max_size=200
hibernate.c3p0.min_size=5
hibernate.c3p0.timeout=12000
hibernate.c3p0.max_statements=50

八、避坑指南速查

  1. ❌ 生產環境直接用 JDK 預設 GC/堆設定 → ✅ 依負載測試調整
  2. ❌ Tomcat 直暴露 8080 給用戶 → ✅ Nginx 反代、隱藏內部端口
  3. ❌ 盲目開啟 Session 複寫 → ✅ 評估 Redis 共享或 Sticky Session
  4. ❌ 忽略 GC 日誌 → ✅ 持久化 GC 日誌、定期分析
  5. ❌ 壓測腳本過於複雜 → ✅ 從單一介面漸進式驗證(登入 → 查詢 → 寫入 → 混合)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved