原理剖析(第 013 篇)應用系統性能調優

原理剖析(第 013 篇)應用系統性能調優

-前端

1、大體介紹

1. 本人接手的一個打車系統,由於出現了一次響應十分緩慢的狀況,所以纔有了應用調優的篇章;
二、因爲過程當中可能沒有闡述的太清楚,如想詳細瞭解能夠留言之類的,但願其中的點點滴滴對你們有所幫助;

2、調優背景

在某一個月黑風高的夜晚,21點多之後,許許多多的小夥伴都相繼下班了,而後你們開始習慣性的掏出本身心愛的手機,
點擊了公司的打車應用App,大概在 21:00 ~ 21:30 期間還風平浪靜的,可是就在 21:30 ~ 21:40 的樣子,忽然打車應用App
響應很是緩慢,App頁面上的菊花一直轉個不停,直到App請求超時菊花才消失, 而後用戶仍是不停的點擊App,由於這個時候
小夥伴們都急着回家,都相繼不停的請求下單,獲取詳情等頁面操做,體驗很是不友好;
    由於出現了這麼一次狀況,雖然沒有給用戶沒有給公司帶來什麼損失,可是該現象從側面已經反應出了系統某些方面的
問題,或許系統參數須要優化一番,或許系統設計交互須要優化一番,或許等等等的可能,纔有了後續系統調優的歷程。

3、計劃分析

一、流程相關分析優化:看看哪些流程能夠同步轉異步處理,App哪些請求能夠合併起來,Server哪些業務場景須要補償機制等。

二、數據庫相關分析優化:哪些Sql耗時較長,哪些方法能夠去除事務且去除事務後的帶來的問題場景分析,數據庫鏈接池參數
                       是否合理,數據庫自己相關參數的閾值狀況的一些綜合考慮;

三、內存使用狀況分析優化:新老年代內存使用率及回收狀況,CPU使用率,磁盤使用率,swap區使用狀況, 線程dump,堆dump。

四、JVM參數分析調優:YGC的平均耗時,YGC的平均間隔,FGC的平均耗時,FGC的平均間隔等等,根據具體狀況反映具體問題;

五、TCP/Tomcat參數分析調優:這個得根據實際壓測狀況來相應評估是否須要調整;

4、Linux命令相關查看指標

4.1 CPU 指標

一、    vmstat n m
    每n秒採集一次,一共採集m次,r:表示運行隊列,r值通常負載超過了3就比較高,超過了5就高,超過了10就不正常了;
    bi和bo通常都要接近0,否則就是IO過於頻繁 )

    [root@svr01]$ vmstat 1 3
    procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
    r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
    0  0 206944 633564  29876 1252176    0    0    10    27    0    0  1  1 98  0  0
    0  0 206944 634232  29876 1252192    0    0     0     0  811 1504  1  1 98  0  0
    0  0 206944 634480  29876 1252264    0    0     0     0  951 1458  6  1 93  0  0
   
二、    uptime
    最近1分鐘,5分鐘,15分鐘的系統平均負載, 
    <=3 則系統性能較好。
    <=4 則系統性能能夠,能夠接收。
    >5 則系統性能負載太重,可能會發生嚴重的問題,那麼就須要擴容了,要麼增長核
    
    [root@svr01]$ uptime
    21:27:44 up 207 days, 11:15, 1 user, load average: 26.45, 16.76, 7.50
    
三、    top
    主要看us和sy,其中us<=70,sy<=35,us+sy<=70說明狀態良好,
    同時能夠結合idle值來看,若是id<=70 則表示IO的壓力較大。

4.2 Memory 指標

一、    vmstat        
    swpd:虛擬內存已使用的大小,若是大於0,表示你的機器物理內存不足了 
    每秒從磁盤讀入虛擬內存的大小,若是這個值大於0,表示物理內存不夠用或者內存泄露了,要查找耗內存進程解決掉。
    so:每秒虛擬內存寫入磁盤的大小,若是這個值大於0,同上,單位爲KB。     

    [root@svr01]$ vmstat 1 3
    procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
    r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
    0  0 206944 633564  29876 1252176    0    0    10    27    0    0  1  1 98  0  0
    0  0 206944 634232  29876 1252192    0    0     0     0  811 1504  1  1 98  0  0
    0  0 206944 634480  29876 1252264    0    0     0     0  951 1458  6  1 93  0  0

4.3 Disk 指標

一、    df
    Use%:已使用佔比,Use% <= 90% 表示還勉強接受正常
    
    [root@svr01]$ df
    Filesystem           1K-blocks     Used Available Use% Mounted on
    /dev/mapper/VolGroup00-LVroot
                          17737040  4286920  12542448  26% /
    tmpfs                  1893300        0   1893300   0% /dev/shm
    /dev/sda1               194241   127341     56660  70% /boot
    /dev/mapper/VolGroup00-LVhome
                            487652     2348    459704   1% /home
    /dev/mapper/VolGroup00-LVcloud
                           3030800   260440   2613076  10% /opt/cloud
    /dev/mapper/VolGroup00-LVtmp
                           8125880    18724   7687728   1% /tmp
    /dev/mapper/VolGroup00-LVvar
                          25671996   848996  23512280   4% /var
    /dev/mapper/VolGroup1-LVdata1
                          41149760 33707952   5344864  87% /wls/applogs

4.4 Disk IO 指標

一、    sar -d 1 1
    查看磁盤報告 1 1 表示間隔1s,運行1次
    
    若是svctm的值與await很接近,表示幾乎沒有I/O等待,磁盤性能很好,若是await的值遠高於svctm的值,
    則表示I/O隊列等待太長,系統上運行的應用程序將變慢。
    
    若是%util接近100%,表示磁盤產生的I/O請求太多,I/O系統已經滿負荷的在工做,該磁盤請求飽和,可能存在瓶頸。
    idle小於70% I/O壓力就較大了,也就是有較多的I/O。                                            
                                                    
    [root@svr01]$ sar -d 1 1
    Linux 2.6.32-642.6.2.el6.x86_64 (SHB-L0044551) 07/20/2018 _x86_64_ (1 CPU)

    03:00:23 PM DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util
    03:00:24 PM dev252-0 23.00 808.00 80.00 38.61 9.88 375.35 43.48 100.00
    03:00:24 PM dev252-16 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
    03:00:24 PM dev253-0 4.00 448.00 0.00 112.00 1.11 222.00 249.50 99.80
    03:00:24 PM dev253-1 50.00 400.00 0.00 8.00 24.40 523.20 20.00 100.00
    03:00:24 PM dev253-2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
    03:00:24 PM dev253-3 3.00 32.00 0.00 10.67 0.99 242.33 331.67 99.50
    03:00:24 PM dev253-4 0.00 0.00 0.00 0.00 1.61 0.00 0.00 100.00
    03:00:24 PM dev253-5 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
    03:00:24 PM dev253-6 3.00 0.00 24.00 8.00 1.30 393.67 261.33 78.40

    Average: DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util
    Average: dev252-0 23.00 808.00 80.00 38.61 9.88 375.35 43.48 100.00
    Average: dev252-16 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
    Average: dev253-0 4.00 448.00 0.00 112.00 1.11 222.00 249.50 99.80
    Average: dev253-1 50.00 400.00 0.00 8.00 24.40 523.20 20.00 100.00
    Average: dev253-2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
    Average: dev253-3 3.00 32.00 0.00 10.67 0.99 242.33 331.67 99.50
    Average: dev253-4 0.00 0.00 0.00 0.00 1.61 0.00 0.00 100.00
    Average: dev253-5 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
    Average: dev253-6 3.00 0.00 24.00 8.00 1.30 393.67 261.33 78.40

4.5 Network IO 指標

一、    netstat -nat |awk '{print $6}'|sort|uniq -c|sort -rn

    在不考慮系統負載、CPU、內存等狀況下,netstat監控大量ESTABLISHED鏈接與Time_Wait鏈接

    [root@svr01]$ netstat -nat |awk '{print $6}'|sort|uniq -c|sort -rn
        265 TIME_WAIT
         45 ESTABLISHED
         38 CLOSE_WAIT
         18 LISTEN
          8 FIN_WAIT2
          2 SYN_SENT
          1 Foreign
          1 established)

5、一些關於統計的量化指標

注意:有些命令通用,有些是我根據系統的日誌文件格式利用awk/sed兩個命令結合寫出來的。

一、netstat -nat |awk '{print $6}'|sort|uniq -c|sort -rn ( 查看TCP鏈接狀態 )

二、netstat -n|grep TIME_WAIT|awk '{print $5}'|sort|uniq -c|sort -rn|head -n20( 查找較多time_wait鏈接 )

三、netstat -anlp|grep tcp |awk '{print $5}' |awk -F':' '{print $1}' |uniq -c |sort -nr | head -n3( 查出訪問靠前的IP地址 )

四、cat hmilyylimh_sql.log | awk '{print $6}' | awk -F'ms' '{print $1}' | awk -F'=' '{print $2 | "sort -r -n"  }' | head -n5( 查詢sql文件中耗時最高的前5個耗時數據值 )

五、cat hmilyylimh_supp.log | awk '{print $10}' | awk -F'timeConsuming=' '{print $2 }' | awk -F'ms' '{print $1 | "sort -r -n" }' | head -n5( 查看supp文件中耗時最高的前5個耗時數據值 )

六、cat hmilyylimh_sql.log | grep 'sql:=' | awk '{print $5}' | uniq -c | sort -rn | head -n2( 查詢sql文件總共打印了多少條SQL日誌 )

七、cat hmilyylimh_sql.log | grep 'NormalTimeConsuming' | awk '{print $5}' | uniq -c | sort -rn | head -n2( 查看sql文件成功執行了多少條SQL日誌 )

八、cat hmilyylimh_sql.log | grep 'BadTimeConsuming' | awk '{print $5}' | uniq -c | sort -rn | head -n2( 查看sql文件失敗或者異常執行了多少條SQL日誌 )

九、cat hmilyylimh_supp.log | grep 'sendReqSupp start'| awk '{print $6$7$8}' | uniq -c | sort -nr | head -n2( 查詢supp文件sendReqSupp start字符串出現的次數 )

十、lsof -n | awk '{print $1,$2}' | sort | uniq -c | sort -nr | head -n10( 統計持有各個進程持有句柄數最高的10個 )

十一、lsof -n | awk '{print $1,$2}' | sort | uniq -c | sort -nr | awk '{ sum+=$1 };END { print sum } '( 計算全部進程持有句柄數的總和,ulimit -n命令查看最大句柄數 )

十二、lsof | awk 'NF == 9 { print $0}' | sort +6 -7nr | head -n10( 查看系統打開的大文件列表 )

1三、top -b -n 1 | grep -E 'Cpu\(s\)|Mem|Swap'( 一次性查出系統當前的CPU、內存、交換區的狀況 )

1四、iostat -p sda | awk -F'Device' '{ print $1 }'( 查看cpu的統計信息(平均值) )

1五、cat access_log.`date +%Y%m%d`.txt | awk '{print $6}' | uniq -c | sort -k2 -r | head -n10( 統計每秒請求併發,按照時間降序排列 )

1六、cat access_log.`date +%Y%m%d`.txt | awk '{print $6}' | uniq -c | sort -rn | head -n10( 統計每秒併發,按照併發量降序排列 )

1七、cat access_log.`date +%Y%m%d`.txt | awk '{ sum+=$NF }; END { print sum*2/8/1024/1024, "M" }'( 查看訪問hmilyylimh服務器天天的總流量 )

1八、cat gc.log | tail -n20|awk '{print $4}'| awk -F'->' '{print $1, $2, $3 }'| awk -F'(' '{print $1, $2, $3}' | awk -F')' '{print $1}' | awk -F'K' '{print $1/$3*100,  "% used  ->     "  ,$2/$3*100, "% used     " , 100-$2/$3*100, "% free      ",  $3/1024, "M total     ---    新生代" }'( 查看gc指標,新生代最後n條記錄的新生代內存變化率 )

1九、cat gc.log | tail -n20 | awk '{print $7}' | awk -F'->' '{print $1, $2, $3 }' | awk -F'(' '{print $1, $2, $3}' | awk -F')' '{print $1}' | awk -F'K' '{print $1/$3*100,  "% used  ->     "  ,$2/$3*100, "% used     " , 100-$2/$3*100, "% free      ",  $3/1024, "M total     ---    堆內存" }'( 查看最後10條GC日誌的堆內存已使用轉化率 )

20、cat /etc/sysctl.conf | grep 'tcp_'( 查看TCP參數設置信息 )

2一、cat hmilyylimh.log | awk '{if($2>"15:17:00.236") print $0}' | grep "max_user_connections" | wc -l( 查看具體時間點後某個字符串出現的次數 )

6、系統經常使用計數器命令

一、echo "<<<<<<<<<<<<<< 線程阻塞等待計數: "`less hmilyylimh_error.log | grep "with callerRunsPolicy" | wc -l`",   ""db事務嵌套鎖AcquireLock計數: "`less hmilyylimh_error.log | grep "CannotAcquireLockException" | wc -l`",   ""建立事務異常計數: "`less hmilyylimh_error.log | grep "CannotCreateTransactionException" | wc -l`",    ""db鏈接池溢出計數: "`less hmilyylimh_error.log | grep "more than 'max_user_connections'" | wc -l`",    ""Pool Empty計數: "`less hmilyylimh_error.log | grep "Unable to fetch a connection" | wc -l`" >>>>>>>>>>>>>>"

二、echo "<<<<<<<<<<<<<< UnknownHostException計數: "`less hmilyylimh_error.log | grep "UnknownHostException" | wc -l`",   ""ConnectionPoolTimeout計數: "`less hmilyylimh_error.log | grep "ConnectionPoolTimeout" | wc -l`",   ""ConnectException計數: "`less hmilyylimh_error.log | grep "ConnectException" | wc -l`",   ""ConnectTimeoutException計數: "`less hmilyylimh_error.log | grep "ConnectTimeoutException" | wc -l`",   ""SocketTimeoutException計數: "`less hmilyylimh_error.log | grep "SocketTimeoutException" | wc -l`",   ""OtherException計數: "`less hmilyylimh_error.log | grep "OtherException" | wc -l`" >>>>>>>>>>>>>>"

三、echo "<<<<<<<<<<<<<< Sql耗時最高的前5個數值: "`cat hmilyylimh_sql.log | awk '{print $6}' | awk -F'ms' '{print $1}' | awk -F'=' '{print $2 | "sort -r -n"  }' | head -n5`",   ""Supp耗時最高等待前5個數值: "`cat hmilyylimh_supp.log | awk '{print $10}' | awk -F'timeConsuming=' '{print $2 }' | awk -F'ms' '{print $1 | "sort -r -n" }' | head -n5`" >>>>>>>>>>>>>>"

四、echo "<<<<<<<<<<<<<< Http請求耗時最高前10個數值: "`less hmilyylimh.log | grep "timeConsuming=" | awk '{print $9}' | awk -F'=' '{print $2}' | awk -F'ms' '{print $1 | "sort -r -n"  }' | head -n10`" >>>>>>>>>>>>>>"

7、流程相關分析優化

1. 經過 access_log.txt 日誌分析,在特定時間段內,將請求至系統的 url 分組計數,最後會出一個根據url調用次數的排序;

二、針對請求次數首屈一指的url接口,在分析完業務場景後,決定將高頻率的接口優化成同步轉異步;

三、然而想查看Server端每一個Http請求的耗時時間,卻發現沒有相關功能點統計,因而乎又新增切面Aspect來統計Client請求至
   Server的耗時統計日誌,而後經過 less,grep,awk 命令來分析耗時最高的url請求,後續可作成監控及時發現長耗時請求;

四、一樣發現請求下游系統也沒有相關耗時統計,所以依葫蘆畫瓢再次新增請求下游系統切面來統計耗時狀況;

五、在後續的壓測過程當中,效果顯著,單臺服務器的TPS提高了3倍,並且在壓測過程不斷打出線程dump, 堆dump日誌,而後
   重點將 hmilyylimh_20180716-143726.threads 放到網頁中分析,結果發現一個比較嚴重的問題,Log4J 1.x blocked 
   問題,總計大概有90多個線程在等待同一把鎖。因而乎將應用的 log4j 1.x 版本升級至 log4j 2.x 版本。可是呢,官方
   明確說明:Log4j 2.4 and greater requires Java 7, versions 2.0-alpha1 to 2.3 required Java 6。所以咱們就只好
   採用了2.3版本。
   
六、後面還考慮了將請求下游系統的日誌作成了異步打印,效果更佳;   
   
七、經過和前端溝通,將一些請求進行了進行了聚合處理返回給前端,在某種程度上友好的提高了交互體驗;   

八、針對支付場景的支付狀態同步新增了補償機制,後臺主動查詢下游系統訂單的支付狀態,最大力度的保證用戶看到的支付
   狀態是準實時的;
   
九、針對Http的工具類,根據業務的實際狀況定製一套超時參數,儘可能減小Http鏈接長時間被Hold住不釋放,必要時Http請求
   工具類作相應的嘗試次數控制;   

十、最後的壓測也比較簡單,經過寫程序操控狀態扭轉,將整個打車流程走完,程序只須要傳入人數來壓測系統最高負荷;   
   
   通過後續壓測顯示,日誌鎖顯然不存在了,最後一次統計的數據得知TPS相比最初提高了至少5倍以上,因而可知流程的優化
和日誌的優化對於系統的性能提高有很大的幫助;

8、數據庫相關分析優化

一、經過收集產線出問題時刻的數據庫指標( max_used_connections/max_user_connections/max_connections ),除了這三個
   參數意外,還收集了數據庫鏈接超時時間,出問題時刻數據庫實例先後幾個小時的時序分析圖;

二、在測試環境壓測狀況下,然後臺應用的鏈接池的參數配置爲:

   嘗試步驟一:
   (max_connections=160, max_user_connections=80, 兩臺1核2G的服務器)
   tomcat.initialSize=25
   tomcat.validationInterval=25000
   tomcat.maxActive=85
   tomcat.minIdle=25
   tomcat.maxIdle=25
   結論:系統部署重啓後直接啓動不起來,報的什麼錯已經忘記了,而後繼續調整鏈接池參數;
   
   
   嘗試步驟二:
   (max_connections=160, max_user_connections=80, 兩臺1核2G的服務器)
   tomcat.initialSize=12
   tomcat.validationInterval=25000
   tomcat.maxActive=85
   tomcat.minIdle=12
   tomcat.maxIdle=12
   結論:系統能正常啓動,相對於步驟一來講,鏈接池的合理配置很是重要,可是在壓測狀況下發生了一些異常;
   --- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: User hmily already has more than 
   'max_user_connections' active connections,因而乎繼續後續步驟;
   
   
   嘗試步驟三:
   (max_connections=160, max_user_connections=80, 兩臺1核2G的服務器)
   tomcat.initialSize=12
   tomcat.validationInterval=25000
   tomcat.maxActive=80
   tomcat.minIdle=12
   tomcat.maxIdle=12
   結論:相對於步驟二來講,異常仍是有一些,數據庫的 160 剛剛等於 tomcat.maxActive * 2 = 160,
   可是又引起了另一個異常:
   Cause: org.apache.tomcat.jdbc.pool.PoolExhaustedException: [http-nio-0.0.0.0-40009-exec-91] Timeout: Pool
   empty. Unable to fetch a connection in 5 seconds, none available[size:40; busy:3; idle:37; lastwait:5000];
   因而乎繼續後續步驟;
   
   
   嘗試步驟四:
   (max_connections=160, max_user_connections=80, 兩臺1核2G的服務器)
   tomcat.initialSize=12
   tomcat.validationInterval=25000
   tomcat.maxActive=80
   tomcat.minIdle=12
   tomcat.maxIdle=12
   結論:相對於步驟二來講,異常仍是有一些,數據庫的 160 剛剛等於 tomcat.maxActive * 2 = 160,
   可是仍是會引起了另一個異常:
   Cause: org.apache.tomcat.jdbc.pool.PoolExhaustedException: [http-nio-0.0.0.0-40009-exec-91] Timeout: Pool
   empty. Unable to fetch a connection in 5 seconds, none available[size:40; busy:3; idle:37; lastwait:5000];
   因而乎繼續後續步驟;
   
   在這一步,咱們沒法計算每一個SQL的耗時狀況,因而集成了SqlMapClientTemplate類,在SqlMapClientTemplate的擴展類
   中針對queryForObject、queryForList、update、delete主流的方法進行了before/after/finally加強處理打印SQL耗時;
   
   
   嘗試步驟五:
   (max_connections=160, max_user_connections=80, 兩臺1核2G的服務器)
   tomcat.initialSize=12
   tomcat.validationInterval=25000
   tomcat.maxActive=40
   tomcat.minIdle=12
   tomcat.maxIdle=12
   結論:在步驟四中,經過將maxActive改回40, 且對耗時的SQL進行優化處理,同時對一些不常變化的SQL配置進行了緩存
   處理,這樣一來在壓測高併發的狀況下,全部狀況所有有所好轉,一切正常自如;
   
   可是我遠不知足於此,而後我又開始調整鏈接池參數配置;
   
   
   嘗試步驟六:
   (max_connections=320, max_user_connections=160, 兩臺1核2G的服務器)
   tomcat.initialSize=12
   tomcat.validationInterval=25000
   tomcat.maxActive=80
   tomcat.minIdle=12
   tomcat.maxIdle=12
   結論:以前出現的異常也沒有了,因而我綜合以上個人各類嘗試,實際測試總結了一些關於我的理解的參數配置;
   

三、小結:
   對於鏈接池這塊,想必你們也一樣都是從網上摘抄下來的配置,雖然調整後的配置不必定是最佳的,可是對整個應用沒有
起到反作用的話,那就是對應用最適合的配置。並且你們在配置的時候,還得綜合考慮服務器水平擴展後對數據庫的一個壓力
狀況,調整的時候必定要參照數據庫實例的參數配置來綜合考慮衡量應用的參數配置。

    
   #初始化鏈接: 鏈接池啓動時建立的初始化鏈接數量
   tomcat.initialSize=12      
   -- 緣由:線程快照圖最小鏈接數爲22,目前因爲業務量大,僅僅只是2臺服務器,考慮到後續的業務還會繼續擴大,
      由於該參數不適宜調整的過高,根據實際狀況最後調整爲12。

   #避免過分驗證,保證驗證不超過這個頻率——以毫秒爲單位
   tomcat.validationInterval=25000      
   -- 緣由:數據庫的鏈接超時時間是29秒,咱們儘量小於數據庫的鏈接超時時間

   #最大活動鏈接: 鏈接池在同一時間可以分配的最大活動鏈接的數量,若是設置爲非正數則表示不限制
   tomcat.maxActive=50      
   -- 緣由:線程快照圖的最大鏈接數爲82,目前產線只有2臺服務器,最大也就是 50 * 2 = 100,還遠遠小於 
   max_user_connections數值,最初是滴測試狀況調整的爲40,而產線的服務器性能絕對比測試環境好,綜合評估定位50。

   #最小空閒鏈接: 鏈接池中允許保持空閒狀態的最小鏈接數量, 低於這個數量將建立新的鏈接, 
   若是設置爲0則不建立.默認與initialSize相同
   tomcat.minIdle=12      
   -- 緣由:考慮和initialSize調整爲同樣的

   #最大空閒鏈接: 鏈接池中允許保持空閒狀態的最大鏈接數量, 超過的空閒鏈接將被釋放, 若是設置爲負數表示不限制
   tomcat.maxIdle=12      
   -- 緣由:考慮和minIdle同樣

9、內存使用狀況分析優化

一、經過 awk 命令分析gc日誌文件,發現老年代還有較多的空間能夠利用,因而就是看看哪些是能夠不常常變化的配置,儘可能
   減小數據庫IO的操做,最大程度先去讀取緩存,緩存沒有再去從數據庫中加載數據。

二、在壓測的過程當中,儘可能多一些headDump文件,而後經過 eclipse 工具來分析看看都有哪些大對象,也沒有發現任何有疑點
   的地方,因而反查代碼,在一些定時任務須要加載大量數據的地方,當加載出來的數據用完以後直接手動釋放,儘快讓垃圾
   回收期回收內存。
   
三、還有一點就是,在一些後臺定時輪詢的任務中,有些任務須要經過for循環來處理一些任務,這個時候咱們能夠每循環一次
   或者循環數次以後經過調用Thead.sleep(xxx)休眠一下,一是能夠緩衝一下IO高密度的操做,還有就是讓出CPU時間片,
   讓有些緊急的任務能夠優先獲取CPU執行權。
   
四、作完這些後,壓測後經過GC日誌分析,老年代內存相比未優化前多了一些,可是性能吞吐率卻大大的獲得了提升,磁盤IO
   的TPS也在必定程度上下降了。

10、JVM參數分析調優

一、爲了應對未來的高業務量,目前須要擴容服務器,將2臺服務器擴容至4臺服務器,而後將服務器由2核4G升級成爲4核8G。
   所以在升級過程當中對於參數的調整也存在了必定的迷惑期。
   
二、JVM參數的調整測試過程一兩句話也說不清,這裏我就講解一下大體的思路:
    • YGC的平均耗時,YGC的平均間隔,能夠經過GC日誌完整分析出來,根據實際狀況是否須要調整堆大小,年輕代佔比,存活區佔比;   
    • FGC的平均耗時,FGC的平均間隔,一樣能夠經過GC日誌完整分析出來,重點關注FGC耗時,想辦法調整堆大小,年輕代佔比,存活區佔比,垃圾回收器方式;
    • S2區的使用佔比,若是S2佔比爲0,且YGC平均耗時也在40ms之內的話,也沒有FGC,這也算是相對比較理想的狀況;
    • S2區滿的話,FGC頻繁或者GC效果不好時建議調整堆大小,還得不到改善就要開發分析實際Heap消耗的對象佔比了;    
    
三、最後附上個人4核8G的JVM參數狀況以下:

   -Xms2048M -Xmx2048M -Xss256k 
   -XX:NewSize=512m -XX:MaxNewSize=512m -XX:SurvivorRatio=22 
   -XX:PermSize=256m -XX:MaxPermSize=512m 
   -XX:+UseParNewGC -XX:ParallelGCThreads=4 -XX:+ScavengeBeforeFullGC 
   -XX:+CMSScavengeBeforeRemark -XX:+UseCMSCompactAtFullCollection 
   -XX:CMSInitiatingOccupancyFraction=60 -XX:CMSInitiatingPermOccupancyFraction=70 
   -XX:+PrintGCApplicationConcurrentTime -XX:+PrintHeapAtGC -XX:+HeapDumpOnOutOfMemoryError 
   -XX:HeapDumpPath=logs/oom.log -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 
   -verbose:gc -Xloggc:logs/gc.log -Djava.net.preferIPv4Stack=true
   
四、GC優化的一點建議:
       • Minor GC 執行很是迅速 ( 建議 50ms 之內 )
       • Minor GC 沒有頻繁執行 ( 建議大約 10s 執行一次 )
       • Full GC 執行很是迅速 ( 建議 1000ms 之內 )
       • Full GC 沒有頻繁執行 ( 建議大約 10min 執行一次 )

11、TCP/Tomcat參數分析調優

一、在測試壓測過程當中,因爲很大提高系統應用的請求併發,所以須要調整Tomcat中相關的參數,maxThreads、acceptCount
   (最大線程數、最大排隊數),也就是說須要查看 tomcat的Connector、Executor 全部屬性值,但產線本人並未作相應調整;

二、在壓測過程當中,發現大量的TIME-WAIT的狀況,因而根據實際調整系統的TCP參數,在高併發的場景中,TIME-WAIT雖然會峯
   值爬的很高,可是降下來的時間也是很是快的,主要是須要快速回收或者重用TCP鏈接。
   
三、最後附上個人4核8G的TCP參數狀況以下:
   vim /etc/sysctl.conf                
   #編輯文件,加入如下內容:                
   net.ipv4.tcp_syncookies = 1                
   net.ipv4.tcp_tw_reuse = 1                
   net.ipv4.tcp_tw_recycle = 1                
   net.ipv4.tcp_fin_timeout = 30                
   #而後執行 /sbin/sysctl -p 讓參數生效。

12、小結

總而言之,通過這一系列的分析調優下來,對於系統來講,應用的系統性能提高至關可觀,同時也在優化的過程當中創建起了
一套本身獨有的思考方式,雖然說目前優化下來的這套配置並非最完美的,可是它確實最適合系統的。
   以上這些數據值僅供參考,若是你們有更好的方式或者更優雅的調優方式,也歡迎你們一塊兒來多多討論。

十3、下載地址

https://gitee.com/ylimhhmily/SpringCloudTutorial.gitjava

SpringCloudTutorial交流QQ羣: 235322432mysql

SpringCloudTutorial交流微信羣: 微信溝通羣二維碼圖片連接ios

歡迎關注,您的確定是對我最大的支持!!!git

相關文章
相關標籤/搜索