Tomcat 預設配置面向開發測試,生產環境必須針對 JVM 記憶體、連接器線程池、安全防護、靜態資源處理進行系統化調優。本文整理適用於 Tomcat 5 至 9 的核心優化項目,附參數說明與建議值。
Tomcat 本身不管理堆記憶體,由啟動腳本傳遞 JVM 參數控制。務必在專用腳本或環境變數中設定,勿直接修改 catalina.sh/bat,便於版本升級與多實例管理。
建立 setenv.sh (Linux/Unix) 或 setenv.bat (Windows) 放於 $CATALINA_HOME/bin/,Tomcat 啟動時自動讀取。
# setenv.sh (Linux/Unix)
export CATALINA_OPTS="-server -Xms2g -Xmx2g -XX:NewSize=512m -XX:MaxNewSize=512m -XX:SurvivorRatio=8 -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$CATALINA_HOME/logs/heapdump.hprof"
# 如需 JMX 遠程監控(生產環境請加認證與 SSL)
# export CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9004 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=192.168.1.100"
rem setenv.bat (Windows)
set CATALINA_OPTS=-server -Xms2g -Xmx2g -XX:NewSize=512m -XX:MaxNewSize=512m -XX:SurvivorRatio=8 -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=%CATALINA_HOME%\logs\heapdump.hprof
| 參數 | 含義 | 建議策略 |
|---|---|---|
| -Xms / -Xmx | 堆初始/最大值 | 設為相同值,避免動態擴縮容震盪;物理記憶體 60%-70% 給堆,預留 30%-40% 給 Metaspace、Code Cache、Thread Stack、OS、文件緩存 |
| -XX:NewSize / -XX:MaxNewSize | 新生代固定大小 | 設為堆的 1/4 ~ 1/3,減少 Minor GC 頻率 |
| -XX:SurvivorRatio=8 | Eden:Survivor=8:1:1 | 預設 8 通常足夠,大對象直接進老年代 |
| -XX:MetaspaceSize / -XX:MaxMetaspaceSize | 元空間大小 (JDK 8+) | 固定 256m/512m,避免 Full GC 觸發類卸載 |
| -XX:+UseG1GC | 啟用 G1 收集器 | JDK 9+ 預設;大堆(>4g)低延遲首選,配合 -XX:MaxGCPauseMillis |
| -XX:+HeapDumpOnOutOfMemoryError | OOM 時自動導出堆快照 | 必開,配合 -XX:HeapDumpPath 指定目錄,事後用 MAT/Eclipse Memory Analyzer 分析 |
Tomcat 使用 Executor 共享線程池或 Connector 獨立線程池。高並發場景建議顯式配置 Executor。
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="800" minSpareThreads="100" maxIdleTime="60000"
prestartminSpareThreads="true" />
<Connector executor="tomcatThreadPool"
port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
redirectPort="8443"
maxConnections="10000"
acceptCount="1000"
enableLookups="false"
disableUploadTimeout="true"
compression="on"
compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json"
compressionMinSize="2048"
URIEncoding="UTF-8"
maxHttpHeaderSize="8192"
maxPostSize="2097152" />
| 參數 | 預設值 | 建議值(高並發) | 說明 |
|---|---|---|---|
| maxThreads | 200 | 500-1000 | 最大工作線程數,Executor 模式下由 Executor 控制 |
| minSpareThreads | 10 | 50-100 | 最小閒置線程,預熱避免突發延遲 |
| maxConnections | 10000 | 10000-20000 | NIO 模式最大連接數,超過進入 acceptCount 隊列 |
| acceptCount | 100 | 500-1000 | 等待隊列長度,拒絕連接前緩衝 |
| enableLookups | true | false | 禁用 DNS 反查,顯著降低延遲 |
| connectionTimeout | 20000 | 30000 | 毫秒,0 表永不超時(不建議) |
| compression | off | on | 啟用 GZIP 壓縮,節省頻寬 |
| protocol | HTTP/1.1 | org.apache.coyote.http11.Http11NioProtocol | NIO 非阻塞模式,高並發必選 |
預設 DefaultServlet 的 listings 參數為 true,會洩露目錄結構。修改 $CATALINA_HOME/conf/web.xml:
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
在 server.xml <Host> 或 <Engine> 下添加 RemoteAddrValve / RemoteHostValve:
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="192\.168\.1\.\d+|10\.0\.0\.\d+|127\.0\.0\.1" />
<!-- 僅允許內網與本機訪問管理介面 -->
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
deny=".*" />
<!-- 預設拒絕所有,結合 allow 形成白名單 -->
allow、deny 支援正則表達式web.xml 中 DefaultServlet 添加 readonly=true、fileEncoding=UTF-8ExpiresFilter (Tomcat 7+) 或 Nginx expires 指令| 工具 | 用途 | 關鍵指標 |
|---|---|---|
| JConsole / VisualVM | JMX 實時監控 | 堆/非堆記憶體、線程數、GC 頻率耗時、類加載數 |
| PSI Probe | Tomcat 專用 Web 監控 | 會話數、請求處理時間、數據源連接池、應用部署狀態 |
| Access Log Valve | 訪問日誌分析 | QPS、響應時間分布、錯誤率、熱門 URL |
| GC Log + GCViewer | GC 行為分析 | Young/Full GC 耗時、存活對象、堆佔用趨勢 |
Tomcat 優化無銀彈,核心原則:
1. 壓測驅動配置 —— 用 JMeter/Gatling 模擬真實業務模型,觀察瓶頸再調參數
2. 分層監控 —— JVM、Tomcat、OS、DB、網絡全鏈路可觀測
3. 配置即代碼 —— 所有調優參數納入版本控制,CI/CD 流水線自動部署
4. 定期複盤 —— 業務增長、JDK 升級、中間件版本變更均可能引發新瓶頸,建議季度回顧