Tomcat環境及線程池、jdk配置詳解
tomcat 環境及線程池、jdk配置詳解
一、常見的Java內存溢出有以下三種:
- JVM Heap(堆)溢出:java.lang.OutOfMemoryError: Java heap space
JVM在啟動的時候會自動設置JVM Heap的值,其初始空間(即-Xms)是物理內存的1/64,最大空間(-Xmx)不可超過物理內存。
可以利用JVM提供的-Xmn -Xms -Xmx等選項可進行設置。Heap的大小是Young Generation 和Tenured Generaion 之和。
在JVM中如果98%的時間是用于GC,且可用的Heap size 不足2%的時候將拋出此異常信息。
解決方法:手動設置JVM Heap(堆)的大小 </p>2. PermGen space溢出:java.lang.OutOfMemoryError: PermGen space
PermGen space的全稱是Permanent Generation space,是指內存的永久保存區域。
為什么會內存溢出,這是由于這塊內存主要是被JVM存放Class和Meta信息的,Class在被Load的時候被放入PermGen space區域,它和存放Instance的Heap區域不同,sun的 GC不會在主程序運行期對PermGen space進行清理,所以如果你的APP會載入很多CLASS的話,就很可能出現PermGen space溢出。
解決方法:手動設置MaxPermSize大小3. 棧溢出:java.lang.StackOverflowError
棧溢出了,JVM依然是采用棧式的虛擬機,這個和C和Pascal都是一樣的。函數的調用過程都體現在堆棧和退棧上了。
調用構造函數的 “層”太多了,以致于把棧區溢出了。
通常來講,一般棧區遠遠小于堆區的,因為函數調用過程往往不會多于上千層,而即便每個函數調用需要 1K的空間(這個大約相當于在一個C函數內聲明了256個int類型的變量),那么棧區也不過是需要1MB的空間。通常棧的大小是1-2MB的。
通常遞歸也不要遞歸的層次過多,很容易溢出。
解決方法:修改程序。二、解決方法
在生產環境中tomcat內存設置不好很容易出現jvm內存溢出。
1、 linux下的tomcat 位于cygwin=false前
修改TOMCAT_HOME/bin/catalina.sh
export JAVA_HOME="/usr/local/jdk"
export JRE_HOME="/usr/local/jdk/jre"# OS specific support. $var _must_ be set to either true or false.
.............
.............
# Get standard environment variables
PRGDIR=`dirname "$PRG"`# Only set CATALINA_HOME if not already set
[ -z "$CATALINA_HOME" ] && CATALINA_HOME=`cd "$PRGDIR/.." >/dev/null; pwd`# Copy CATALINA_BASE from CATALINA_HOME if not already set
[ -z "$CATALINA_BASE" ] && CATALINA_BASE="$CATALINA_HOME"export CATALINA_OPTS="-server -Xss512k -Xms1024M -Xmx1024M -XX:PermSize=128M -XX:MaxPermSize=256M -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:ParallelGCThreads=8 -verbose:gc -Xloggc:$CATALINA_BASE/logs/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$CATALINA_BASE/ -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=10001 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"
三、jvm參數說明:
-server:一定要作為第一個參數,因為tomcat默認是以一種叫java –client的模式來運行的,server即意味著你的tomcat是以真實的production的模式在運行的
-Xms:java Heap初始大小。把Xms與Xmx兩個值設成一樣是最優的做法。
-Xmx:java heap最大值。把Xms與Xmx兩個值設成一樣是最優的做法。
-XX:PermSize:設定內存的永久保存區初始大小,缺省值為64M。
-XX:MaxPermSize:設定內存的永久保存區最大 大小,缺省值為64M。
-XX:SurvivorRatio=2 :生還者池的大小,默認是2,如果垃圾回收變成了瓶頸,您可以嘗試定制生成池設置
-XX:NewSize: 新生成的池的初始大小。 缺省值為2M。
-XX:MaxNewSize: 新生成的池的最大大小。 缺省值為32M。
如果 JVM 的堆大小大于 1GB,則應該使用值:-XX:newSize=640m -XX:MaxNewSize=640m -XX:SurvivorRatio=16,或者將堆的總大小的 50% 到 60% 分配給新生成的池。調大新對象區,減少Full GC次數。
+XX:AggressiveHeap 會使得 Xms沒有意義。這個參數讓jvm忽略Xmx參數,瘋狂地吃完一個G物理內存,再吃盡一個G的swap。
-Xss:每個線程的Stack大小,“-Xss 15120” 這使得JBoss每增加一個線程(thread)就會立即消耗15M內存,而最佳值應該是128K,默認值好像是512k.
-verbose:gc 現實垃圾收集信息
-Xloggc:gc.log 指定垃圾收集日志文件
-Xmn:young generation的heap大小,一般設置為Xmx的3、4分之一 ,整個堆大小=年輕代大小 + 年老代大小 + 持久代大小。持久代一般固定大小為64m,所以增大年輕代后,將會減小年老代大小。此值對系統性能影響較大,Sun官方推薦配置為整個堆的3/8。
-XX:+UseParNewGC :縮短minor收集的時間
-XX:+UseConcMarkSweepGC :縮短major收集的時間 此選項在Heap Size 比較大而且Major收集時間較長的情況下使用更合適。
-XX:userParNewGC 可用來設置并行收集【多CPU】
-XX:ParallelGCThreads 可用來增加并行度【多CPU】
-XX:UseParallelGC 設置后可以使用并行清除收集器【多CPU】
使用JVisualVM遠程監控Tomcat在tomcat的catalina.sh 中添加如下參數:
set JAVA_OPTS=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port="9004" -Dcom.sun.management.jmxremote.authenticate="false" -Dcom.sun.management.jmxremote.ssl="false"
-Dcom.sun.management.jmxremote.port=9004 指定了 JMX 啟動的代理端口;這個端口就是 Visual VM 要連接的端口
-Dcom.sun.management.jmxremote.ssl ="false" 指定了 JMX 是否啟用ssl
-Dcom.sun.management.jmxremote.authenticate =false指定了不需要密碼認證連接
四、線程池配置:在./conf/server.xml中:
搜索【<Executor name="tomcatThreadPool"】,開啟并調整為:最大線程500(一般服務器足以),最小空閑線程數20,線程最大空閑時間60秒。
<!--2015/03/03 14:32 changee by wangyingchun -->
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="600" minSpareThreads="30" maxIdleTime="60000" />搜索【port="8080"】,開啟并修改<Connector ...>節點,增加executor屬性,如:
<!--2015/03/03 14:32 changee by wangyingchun -->
<Connector executor="tomcatThreadPool"
port="8001" protocol="HTTP/1.1"
connectionTimeout="60000"
redirectPort="443" URIEncoding="UTF-8"
minSpareThreads="30"
maxSpareThreads="300"
enableLookups="false"
disableUploadTimeout="true"
compression="on" compressionMinSize="4096"
noCompressionUserAgents="gozilla, traviata"
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,application/json,application/x-javascript"
maxThreads="600" />
maxThreads:Tomcat可創建的最大的線程數,每一個線程處理一個請求;
minSpareThreads:最小備用線程數,tomcat啟動時的初始化的線程數;
maxSpareThreads:最大備用線程數,一旦創建的線程超過這個值,Tomcat就會關閉不再需要的socket線程;
acceptCount:指定當所有可以使用的處理請求的線程數都被使用時,可以放到處理隊列中的請求數,
就是被排隊的請求數,超過這個數的請求將拒絕連接。
connnectionTimeout:網絡連接超時,單位:毫秒。設置為0表示永不超時,這樣設置有隱患的。通常可設置為30000毫秒。
enableLookups:是否允許DNS查詢
URIEncoding=”UTF-8” 使得tomcat可以解析含有中文名的文件的url
maxSpareThreads 的意思就是如果空閑狀態的線程數多于設置的數目,則將這些線程中止,減少這個池中的線程總數。
minSpareThreads 最小備用線程數,tomcat啟動時的初始化的線程數。
enableLookups 這個功效和Apache中的HostnameLookups一樣,設為關閉。
connectionTimeout 為網絡連接超時時間毫秒數。
maxThreads Tomcat使用線程來處理接收的每個請求。這個值表示Tomcat可創建的最大的線程數,即最大并發數。
acceptCount是當線程數達到maxThreads后,后續請求會被放入一個等待隊列,這個acceptCount是這個隊列的大小,如果這個隊列也滿了,就直接refuse connection五、JNDI配置
[root@slave3 conf]# vi context.xml
mysql驅動包 :http://mirrors.sohu.com/mysql/Connector-J/mysql-connector-java-5.1.34.zip
oracle驅動包:http://www.oracle.com/technetwork/cn/articles/oem/jdbc-112010-094555-zhs.html
tomcat下載地址:http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.56/bin/apache-tomcat-7.0.56.zip
編輯conf下的context.xml文件在Context模塊插入以下Resource信息
<Context>
<Resource name="jdbc/cfgDS"
auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=10.10.5.18)(PORT=1901)))(CONNECT_DATA=(SERVICE_NAME=hccdb)))"
username="mpm"
password="mpm"
maxActive="30"
maxIdle="0"
maxWait="30000" />
<Resource name="jdbc/BookDB"
auth="Container"
driverClassName="com.mysql.jdbc.Driver"
type="javax.sql.DataSource" url="jdbc:mysql://10.10.6.77:3306/amdb?characterEncoding=UTF-8"
username="root"
password="mangocity"
maxActive="30"
maxIdle="0"
maxWait="30000" />
</Context>
驗證:
在WEB-INF/ 下創建 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC
'-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN' ';
<web-app>
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/BookDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app> - 創建jsp文件, index.jsp
<%@ page language="java" import="java.util.,javax.naming.,java.sql.,javax.sql."pageEncoding="UTF-8"%>
<%
Context ctx = new InitialContext();
String strLookup = "java:comp/env/jdbc/BookDB";
DataSource ds =(DataSource) ctx.lookup(strLookup);
Connection con = ds.getConnection();
if (con != null){
out.print("success");
}else{
out.print("failure");
}
%>