一、JVM內存配置優化
主要通過以下的幾個jvm參數來設置堆內存的:
-Xmx512m 最大總堆內存,一般設置為物理內存的1/4
-Xms512m 初始總堆內存,一般將它設置的和最大堆內存一樣大,這樣就不需要根據當前堆使用情況而調整堆的大小了
-Xmn192m 年輕帶堆內存,sun官方推薦為整個堆的3/8
堆內存的組成 總堆內存 = 年輕帶堆內存 + 年老帶堆內存 + 持久帶堆內存
年輕帶堆內存 對象剛創建出來時放在這里
年老帶堆內存 對象在被真正會回收之前會先放在這里
持久帶堆內存 class文件,元數據等放在這里
-XX:PermSize=128m 持久帶堆的初始大小
-XX:MaxPermSize=128m 持久帶堆的最大大小,eclipse默認為256m。如果要編譯jdk這種,一定要把這個設的很大,因為它的類太多了。
?
在開發當中,當一個項目比較大時,依賴的jar包通常比較多,我們都知道,在應用服務器啟動時,會將應用引用到的所有類通過ClassLoader 依次全部加載到內存當中。Java的邏輯內存模型大致分為堆內存、棧內存、靜態內存區,也稱持久區,該區的內存不會被GC回收。堆內存用于存儲類的實例、 數組等引用類型數據,也就是用new生成的對象,都存放在這里,棧內存存儲局部變量(如:方法參數),靜態內存區存儲常量、靜態變量、類元數據信息(方 法、屬性等)。開發當中常遇到的三類內存溢出異常:
- java.lang.OutOfMemoryError: Java heap space異常
表示堆內存空間滿了,如果不是程序邏輯的bug,可能是因為項目中引用的jar比較多,導到內存溢出。JVM默認堆的最小使用內存為物理內存的1/64, 最大使用內存為物理內存的1/4,如8G的物理內存,JVM默認堆的最小和最大內存分別為128m和2048m。通過調整JVM的-Xms(初始內存)和 -Xmx(最大內存)兩個參數加大內存使用限制。 - java.lang.OutOfMemoryError: PermGen space異常
表示靜態內存區滿了,通常是由于加載的類過多導致。jdk8以下版本通過修改JVM的-XX:PermSize和-XX:MaxPermSize兩個參 數,限制靜態區最小和最大內存范圍。jdk8改變了內存模型,將類定義存放到了元數據(MetaspaceSize)空間,而元數據空間是與堆空間共享同 一塊內存區域的,所以在JDK8以后版本不會存在PermGen space異常了,故不用設置此參數。 - java.lang.StackOverflowError異常
表示棧內存溢出。通常是由于死循環、無限遞歸導致。
?
優化方法:(linux與windows都親測有效)
修改Tomcat的內存配置,打開$TOMCAT_HOME/bin/catalina.sh文件(Windows系統是catalina.bat文件),大楖在250行左右,在JAVA_OPTS參數上添加內存參數設置即可。完整的JVM參數設置如下所示:
linux修改TOMCAT_HOME/bin/catalina.sh,在前面加入
JAVA_OPTS="$JAVA_OPTS -server -Xms2048m -Xmx2048m -XX:PermSize=128m -XX:MaxPermSize=256 -Djava.awt.headless=true"
windows修改TOMCAT_HOME/bin/catalina.bat,在前面加入?
set JAVA_OPTS=-server -Xms2048m -Xmx2048m -XX:PermSize=128m -XX:MaxPermSize=256 -Djava.awt.headless=true
?如果是Windows配置服務式的參考我的另一篇博客:
windows下注冊tomcat服務以及設置jvm參數
?
?
-server參數:表示以服務模式啟動,啟動速度會稍微慢一點,但性能會高很多。不加這個參數,默認是以客戶端模式啟動。
java.awt.headless=true參數:與圖形操作有關,適用于linux系統。如生成驗證碼,含義是當前使用的是沒有安裝圖安裝圖形界面的服務器,應用中如果獲取系統顯示有關參數會拋異常。
?
驗證是否配置成功:
可通過jmap -heap proccess_id或者是擦看Tomcat日志查看設置是否成功。
1.通過查看tomcat啟動日志查看;
(1)通過catalina.bat啟動查看日志:
?
2.利用 jps+jmap 查看(bootstrap代表的是tomcat)
E:\tomcat\apache-tomcat-7.0.72\bin>jps
324592 Bootstrap
571396 Jps
237820E:\tomcat\apache-tomcat-7.0.72\bin>jmap -heap 324592
Attaching to process ID 324592, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.80-b11using thread-local object allocation.
Parallel GC with 4 thread(s)Heap Configuration:MinHeapFreeRatio = 0MaxHeapFreeRatio = 100MaxHeapSize = 2147483648 (2048.0MB)NewSize = 1310720 (1.25MB)MaxNewSize = 17592186044415 MBOldSize = 5439488 (5.1875MB)NewRatio = 2SurvivorRatio = 8PermSize = 134217728 (128.0MB)MaxPermSize = 134217728 (128.0MB)G1HeapRegionSize = 0 (0.0MB)Heap Usage:
PS Young Generation
Eden Space:capacity = 537919488 (513.0MB)used = 336902296 (321.2950668334961MB)free = 201017192 (191.7049331665039MB)62.630617316470975% used
From Space:capacity = 89128960 (85.0MB)used = 45512304 (43.40391540527344MB)free = 43616656 (41.59608459472656MB)51.06342988855698% used
To Space:capacity = 89128960 (85.0MB)used = 0 (0.0MB)free = 89128960 (85.0MB)0.0% used
PS Old Generationcapacity = 1431830528 (1365.5MB)used = 8897120 (8.484954833984375MB)free = 1422933408 (1357.0150451660156MB)0.6213808007311882% used
PS Perm Generationcapacity = 134217728 (128.0MB)used = 44075888 (42.03404235839844MB)free = 90141840 (85.96595764160156MB)32.83909559249878% used
?
?
3.通過JDK自帶的jvisualvm.exe工具查看
?
4.通過tomcat自帶的項目(manage)查看:
?
參考:https://www.cnblogs.com/ggjucheng/archive/2013/04/16/3024731.html
?
5.用JDK自帶的jconsole查看:
參考:http://www.cnblogs.com/qlqwjy/p/8304211.html
?
6.利用JDK自帶的JPS命令查看JVM信息:?
jps –v :輸出jvm參數
?
例如: 查看本機所有的JVM參數:
$ jps -v
3732 Jps -Dapplication.home=C:\Program Files\Java2\jdk1.7.0_80 -Xms8m
3740 Bootstrap -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:56098 -Dcatalina.base=E:\tomcat\apache-tomcat-7.0.72 -Dcatalina.home=E:\tomcat\apache-tomcat-7.0.72 -Dwtp.deploy=E:\xiangmu -Djava.endorsed.dirs=E:\tomcat\apache-tomcat-7.0.72\endorsed -Xms5200M -Xmx5200M -XX:PermSize=512M -XX:MaxPermSize=512M -Dfile.encoding=GBK
9556 OracleIdeLauncher -Xbootclasspath/a:C:\Program Files\Oracle\sqldeveloper\jdk\lib\tools.jar;C:\Program Files\Oracle\sqldeveloper\jdk\lib\dt.jar -Dsun.java2d.noddraw=true -Dnetbeans.home=/Program Files/Oracle/sqldeveloper/netbeans/platform/ -Dnetbeans.logger.console=true -Dexcluded.modules=org.eclipse.osgi -Dide.cluster.dirs=/Program Files/Oracle/sqldeveloper/netbeans/fcpbridge/:/Program Files/Oracle/sqldeveloper/netbeans/ide/:/Program Files/Oracle/sqldeveloper/netbeans/../ -Xverify:none -Doracle.ide.extension.HooksProcessingMode=LAZY -Dorg.eclipse.equinox.simpleconfigurator.configUrl=file:bundles.info -Dosgi.bundles.defaultStartLevel=1 -Dosgi.configuration.cascaded=false -Dosgi.noShutdown=true -Dorg.osgi.framework.bootdelegation=* -Dosgi.parentClassloader=app -Dosgi.locking=none -Dosgi.contextClassLoaderParent=app -Xbootclasspath/p:/Program Files/Oracle/sqldeveloper/rdbms/jlib/ojdi.jar -Dosgi.classloader.type=parallel -Dosgi.bundlefile.limit=500 -Dide.feedback-server=ide.us.oracle.com -Djavax.xml.transform.TransformerFactory=or
5292 -Dosgi.requiredJavaVersion=1.7 -Xms3072m -Xmx3072m -XX:PermSize=728m -XX:MaxPermSize=728m -XX:+UseParallelGC -XX:+DisableExplicitGC -Xloggc:gc.log -XX:+PrintGCTimeStamps -XX:+PrintGCDetails
?
?
例如:查看Tomcat的JVM參數: (Bootstrap是Tomcat的信息)
liqiang@root MINGW64 /e/xiangmu/sbgl (qlq)
$ jps -v|grep Bootstrap
3740 Bootstrap -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:56098 -Dcatalina.base=E:\tomcat\apache-tomcat-7.0.72 -Dcatalina.home=E:\tomcat\apache-tomcat-7.0.72 -Dwtp.deploy=E:\xiangmu -Djava.endorsed.dirs=E:\tomcat\apache-tomcat-7.0.72\endorsed -Xms5200M -Xmx5200M -XX:PermSize=512M -XX:MaxPermSize=512M -Dfile.encoding=GBK
?
?
?
二、并發配置優化
主要配置Tomcat能處理的請求數,當一個進程的線程數超過500個的話,那么這個進程的運行效率就很低了。表面上看線程越多處理的請求越多,其 實過多的線程會占用CPU在不同線程之間切換的資源,導致CPU在每個線程上處理的時間片極期有限,反而會降低服務器的響應性能。
<Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol"connectionTimeout="20000"redirectPort="8443" maxThreads="500"minSpareThreads="100"maxSpareThreads="200"acceptCount="200"maxIdleTime="30000"enableLookups="false"/>
?有需要的話在上面標簽最后加上設置tomcat默認編碼格式,如下:
URIEncoding="UTF-8"
?
?
Tomcat的并發請求處理數量=maxThreads + acceptCount
protocol:啟用APR連接模式,提高異步IO處理性能。啟用配置請參考:《開啟Tomcat APR運行模式,優化并發性能》
一般小型項目直接用protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads:最大能接受的請求數,默認為200
minSpareThreads:最少備用線程數,默認初始化,默認為25
maxSpareThreads:最多備用線程數,一旦創建的線程超過這個值,Tomcat就會關閉不再需要的socket線程
acceptCount:等待處理的請求隊列,默認為100,超過隊列長度,服務器則拒絕客戶端請求,直接返回403
maxIdleTime:如果一個線程在30秒以內沒有活躍,則終止運行并從線程池中移除。除非線程池數量小于或等于minSpareThreads數量。默認值是1分鐘
enableLookups:如果為true,調用request.getRemoteHost會執行DNS反查,反向解析IP對應的域名或主機,效率較低,建議設為false。
更多參數設置,請參考Tomcat官方文檔:http://tomcat.apache.org/tomcat-8.0-doc/config/http.html
例如:我的配置(也是我的第一個項目部署的配置)
<Connector URIEncoding="UTF-8"
connectionTimeout="20000"port="80"
protocol="org.apache.coyote.http11.Http11NioProtocol"maxThreads="500"
minSpareThreads="20"
acceptCount="100"disableUploadTimeout="true"
enableLookups="false"
redirectPort="8443" />
?
tomcat啟動后進行查看:
?
?
?參考:https://www.cnblogs.com/ggjucheng/archive/2013/04/16/3024731.html
三、管理員配置
Tomcat默認沒有配置管理員帳戶的權限,如果要查看app的部署狀態、通過管理界面deploy或undeploy,則需要在tomcat-user.xml中配置具有管理權限登錄的用戶。
<role rolename="tomcat"/> <role rolename="manager-gui"/> <role rolename="manager-status"/> <role rolename="manager-script"/> <role rolename="manager-jmx"/> <user username="tomcat" password="tomcat" roles="tomcat,manager-gui,manager-status,manager-script,manager-jmx"/>
?
Tomcat官網配置:http://tomcat.apache.org/tomcat-8.0-doc/manager-howto.html
?
?
?
更多的參數與解釋:http://blog.csdn.net/kthq/article/details/8618052
http://www.cnblogs.com/qlqwjy/p/8010705.html
?