1. 程式人生 > 程式設計 >SpringBoot專案調優及垃圾回收器的比較詳解

SpringBoot專案調優及垃圾回收器的比較詳解

一、SpringBoot專案在外部Tomcat啟動時載入兩次

如下所示,spring標誌出現兩次(擷取部分程式碼)

.  ____     _      __ _ _
 /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/ ___)| |_)| | | | | || (_| | ) ) ) )
 ' |____| .__|_| |_|_| |_\__,| / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::    (v1.5.7.RELEASE)

2020-04-02 16:57:29.505 INFO 19964 --- [ost-startStop-1] com.pitt.kill.server.MainApplication   : Starting MainApplication on LAPTOP-1U9EARRO with PID 19964 (D:\apache-tomcat-8.5.42\apache-tomcat-8.5.42\webapps\kill-0.0.1-SNAPSHOT\WEB-INF\classes started by pitt in C:\Users\pitt\AppData\Local\MyEclipse 2017 CI)
2020-04-02 16:57:29.508 DEBUG 19964 --- [ost-startStop-1] com.pitt.kill.server.MainApplication   : Running with Spring Boot v1.5.7.RELEASE,Spring v4.3.11.RELEASE
2020-04-02 16:57:29.509 INFO 19964 --- [ost-startStop-1] com.pitt.kill.server.MainApplication   : No active profile set,falling back to default profiles: default
2020-04-02 16:57:29.539 INFO 19964 --- [ost-startStop-1] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1e20bc0d: startup date [Thu Apr 02 16:57:29 GMT+08:00 2020]; root of context hierarchy
2020-04-02 16:57:30.097 INFO 19964 --- [ost-startStop-1] o.s.b.f.xml.XmlBeanDefinitionReader   : Loading XML bean definitions from class path resource [spring/spring-jdbc.xml]
2020-04-02 16:57:30.141 WARN 19964 --- [ost-startStop-1] o.m.s.mapper.ClassPathMapperScanner   : No MyBatis mapper was found in '[com.pitt.kill.model.mapper]' package. Please check your configuration.
2020-04-02 16:57:30.258 WARN 19964 --- [ost-startStop-1] o.m.s.mapper.ClassPathMapperScanner   : No MyBatis mapper was found in '[com.pitt.kill.server]' package. Please check your configuration.
2020-04-02 16:57:30.307 INFO 19964 --- [ost-startStop-1] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found,entering strict repository configuration mode!

 .  ____     _      __ _ _
 /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/ ___)| |_)| | | | | || (_| | ) ) ) )
 ' |____| .__|_| |_|_| |_\__,| / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::    (v1.5.7.RELEASE)

2020-04-02 16:57:37.069 INFO 19964 --- [ost-startStop-1] com.pitt.kill.server.MainApplication   : Starting MainApplication on LAPTOP-1U9EARRO with PID 19964 (D:\apache-tomcat-8.5.42\apache-tomcat-8.5.42\webapps\server\WEB-INF\classes started by pitt in C:\Users\pitt\AppData\Local\MyEclipse 2017 CI)
2020-04-02 16:57:37.072 DEBUG 19964 --- [ost-startStop-1] com.pitt.kill.server.MainApplication   : Running with Spring Boot v1.5.7.RELEASE,Spring v4.3.11.RELEASE
2020-04-02 16:57:37.072 INFO 19964 --- [ost-startStop-1] com.pitt.kill.server.MainApplication   : No active profile set,falling back to default profiles: default
2020-04-02 16:57:37.102 INFO 19964 --- [ost-startStop-1] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1565ae71: startup date [Thu Apr 02 16:57:37 GMT+08:00 2020]; root of context hierarchy
2020-04-02 16:57:37.675 INFO 19964 --- [ost-startStop-1] o.s.b.f.xml.XmlBeanDefinitionReader   : Loading XML bean definitions from class path resource [spring/spring-jdbc.xml]
2020-04-02 16:57:37.863 INFO 19964 --- [ost-startStop-1] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found,entering strict repository configuration mode!
2020-04-02 16:57:38.422 INFO 19964 --- [ost-startStop-1] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.amqp.rabbit.annotation.RabbitBootstrapConfiguration' of type [org.springframework.amqp.rabbit.annotation.RabbitBootstrapConfiguration$$EnhancerBySpringCGLIB$$6cdea02f] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-04-02 16:57:38.456 INFO 19964 --- [ost-startStop-1] trationDelegate$BeanPostProcessorChecker : Bean 'shiroConfig' of type [com.pitt.kill.server.config.ShiroConfig$$EnhancerBySpringCGLIB$$4392bed0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

載入時間30s

2020-04-02 16:57:42.825 INFO 19964 --- [ost-startStop-1] com.pitt.kill.server.MainApplication   : Started MainApplication in 6.091 seconds (JVM running for 30.348)
2020-04-02 16:57:42.946 INFO 19964 --- [      main] org.apache.catalina.startup.Catalina   : Server startup in 29361 ms

原因:開啟配置檔案server.xml,Tomcat在啟動web專案時,會首先在Host標籤中找webapps下的專案,進行載入後,又會在Context 標籤中再次載入,導致載入兩次

解決: 將appBase="webapps"替換為appBase = " "

<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
<Context docBase="D:\apache-tomcat-8.5.42\apache-tomcat-8.5.42\webapps\server" path="" reloadable="true" source="org.eclipse.jst.jee.server:server"/>

載入一次時間為12s

2020-04-02 17:03:12.759 INFO 952 --- [ost-startStop-1] com.pitt.kill.server.MainApplication   : Started MainApplication in 7.478 seconds (JVM running for 12.532)
2020-04-02 17:03:13.100 INFO 952 --- [      main] org.apache.catalina.startup.Catalina   : Server startup in 11772 ms

二、禁用位元組碼驗證過程

對類的載入時間進行優化,首先檢視類的載入時間

C:\Program Files\Java\jdk1.8.0_211\bin>jps
16612 QuorumPeerMain
9172 Main
19416 MyEclipse
952 Bootstrap
19580 Jps

C:\Program Files\Java\jdk1.8.0_211\bin>jstat -class 952
Loaded Bytes Unloaded Bytes   Time
 10533 20062.0    0   0.0    7.83

我們預設通過MyEclipse編譯的程式碼是可靠的,不需要在載入的時候進行位元組碼驗證,使用-Xverify:none引數將位元組碼驗證過程禁用掉,來提升類的載入速度

C:\Program Files\Java\jdk1.8.0_211\bin>jstat -class 12308
Loaded Bytes Unloaded Bytes   Time
 9822 18874.2    0   0.0    6.70

提升效果一般,只減少了1s
此外由於HotSpot採用了JIT編譯器可以提前載入熱程式碼,1.8版本JVM的程式碼編譯速度已經比較優秀,此處不做優化

三、調整記憶體設定控制垃圾收集頻率

Java8預設的GC回收器為Parallel Scavenge + Parallel Old

SpringBoot專案調優及垃圾回收器的比較詳解

用Jmeter傳送請求作為輔助測試

可以看到,測試時間內,發起了103次Minor GC,耗時不到1s,其實時間停頓並不多,但是5次Full GC佔用了很大部分的GC時間,主要針對這部分時間進行優化。通過-Xloggc:gc.log -XX:+PrintGCTimeStamps -XX:+PrintGCDetails引數列印GC日誌,將Full GC挑出如下:

7.934: [Full GC (Metadata GC Threshold) [PSYoungGen: 926K->0K(647680K)] [ParOldGen: 54198K->15711K(65024K)] 55125K->15711K(712704K),[Metaspace: 20674K->20674K(1069056K)],0.0303162 secs] [Times: user=0.03 sys=0.00,real=0.03 secs] 
10.430: [Full GC (Metadata GC Threshold) [PSYoungGen: 3883K->0K(646656K)] [ParOldGen: 20986K->17184K(80896K)] 24870K->17184K(727552K),[Metaspace: 34377K->34377K(1081344K)],0.0413074 secs] [Times: user=0.28 sys=0.00,real=0.04 secs] 
379.971: [Full GC (Metadata GC Threshold) [PSYoungGen: 2528K->0K(93696K)] [ParOldGen: 65885K->58730K(132096K)] 68413K->58730K(225792K),[Metaspace: 57642K->57535K(1101824K)],0.3908541 secs] [Times: user=0.97 sys=0.00,real=0.39 secs] 
390.977: [Full GC (Ergonomics) [PSYoungGen: 8688K->0K(230400K)] [ParOldGen: 129221K->120704K(226304K)] 137909K->120704K(456704K),[Metaspace: 62151K->62115K(1105920K)],0.1319683 secs] [Times: user=0.50 sys=0.02,real=0.13 secs] 
553.770: [Full GC (Ergonomics) [PSYoungGen: 47104K->0K(513536K)] [ParOldGen: 228052K->120789K(249344K)] 275156K->120789K(762880K),[Metaspace: 62330K->62330K(1105920K)],0.1344527 secs] [Times: user=0.27 sys=0.02,real=0.13 secs] 

每一次Full GC都伴隨著老年代的擴容,日誌還顯示有時候記憶體回收狀況不理想,獲取可用的記憶體主要通過空間的擴容。
檢視執行期間的CPU使用情況,如下圖:

SpringBoot專案調優及垃圾回收器的比較詳解

垃圾回收的CPU使用率曲線幾乎看不到,CPU資源還有可利用的餘地,為此想到更換原有的垃圾回收器來進行GC優化

CMS:

相比於預設的Parallel GC明顯改善了Full GC所消耗的時間,Stop The World時間減少,但是Minor GC大量增加,嘗試調整新生代的大小來減少Minor GC的產生,在使用-XX:NewRatio=1 -XX:SurvivorRatio=3
-XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=85引數進行調整後,Minor GC數量下降,但是相比而言還是很多

SpringBoot專案調優及垃圾回收器的比較詳解

G1:

G1為最新的垃圾回收演算法,將新生代和老年代同時進行標記和回收,採用標記-整理演算法,不會產生記憶體碎片,在時間消耗上表現的最好,平均每次回收佔用的時間最短,並且最好在記憶體比較大的機器上使用G1演算法進行回收

SpringBoot專案調優及垃圾回收器的比較詳解

G1的優勢在於:
作為CMS的長期替代品
1、G1是一個壓縮收集器,提供足夠強的壓縮來完全避免狹小的記憶體分配
2、依賴Regions概念,大大簡化收集器邏輯,大部分情況下規避潛在的記憶體碎片問題
3、比CMS的GC停頓時長更加可預測,並允許使用者指定停頓時長

總結:

以上三種回收器都為多執行緒垃圾回收器,但是對於不同的環境,應該具體問題具體分析,而不是採用一刀切的方法,解決問題的過程即為尋找最優解的過程。

到此這篇關於SpringBoot專案調優及垃圾回收器的比較詳解的文章就介紹到這了,更多相關SpringBoot專案調優及垃圾回收器內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!