@
系統執行緩慢,執行速度較差雖然沒有對使用者或公司造成實質性的損失,但它從側面反映出系統在某些方面存在問題。可能需要對系統引數進行優化,或者對系統的設計和互動進行調整,這是後續系統效能優化的一個重要過程。我們將繼續努力優化系統,以確保其高效執行和良好效能,以提升使用者體驗並最大程度地滿足業務需求。我們希望通過系統調優的歷程,解決當前存在的問題,並不斷改進系統的執行,為使用者提供更好的服務。
使用 access_log.txt
紀錄檔檔案進行分析,將在指定時間段內請求系統的 URL 進行分組計數,並生成一個根據 URL 呼叫次數進行排序的結果。
注意,為了實現這個目標,你需要使用適當的紀錄檔解析工具或指令碼來提取紀錄檔中的 URL 資訊,並結合時間範圍進行計數和排序。這將幫助你瞭解在特定時間段內哪些 URL 受到了最多的請求,從而可以更好地進行效能優化或其他相關分析工作。
對於請求次數排名靠前的URL介面,在全面分析業務場景後,經過仔細權衡和深入思考,我們決定將這些高頻率的介面從同步呼叫方式轉換為非同步呼叫方式進行優化。
將高頻率的介面優化成非同步呼叫是一項有效的優化策略,可以提升系統的效能和響應速度。但在實施之前,請確保充分理解業務需求和影響,並進行充分測試和評估,使優化方案能夠真正發揮作用,滿足預期的效果。
提升效能和響應速度:通過將這些介面改為非同步呼叫,可以顯著提升系統的效能和響應速度。非同步呼叫方式可以使伺服器能夠更有效地處理並行請求,避免阻塞其他請求的處理,從而提高系統的並行處理能力和吞吐量。
降低延遲和提高效能:這種優化方案的實施需要對介面的呼叫邏輯進行適當的修改和重構。通過合理地設計和運用非同步呼叫策略,可以最大程度地降低介面呼叫的延遲,提高系統的可用性和效能表現。
建議進行詳細的壓力測試和效能評測:以確保在非同步轉換後系統仍能滿足預期的響應和處理能力。
需要考慮業務邏輯的複雜性和介面間的依賴關係:確保所有相關的非同步呼叫都能正確處理異常情況,並設計合適的錯誤處理機制,以確保系統的穩定性和可靠性。
發現在請求下游系統的過程中缺乏相關的耗時統計。為了解決這個問題,我們計劃引入一個新的請求下游系統切面,以便能夠準確地統計每個請求的耗時情況。
通過增加這個切面,我們可以在請求傳送到下游系統並返回結果之間記錄耗時的詳細資訊。這樣做的好處是,我們能夠獲得關於下游系統效能的更全面和準確的資料,從而可以更好地分析和優化系統的效能瓶頸。
為了實現這個切面,我們需要在請求傳送和接收的過程中新增相應的攔截器或勾點,以便能夠計算並記錄下每個請求的耗時。我們還需要在系統中增加相應的統計模組,用來儲存和分析這些耗時資料。
在實施這個方案之前,我們強烈建議進行充分的測試和驗證,以確保新的切面能夠正確地獲取耗時資料,並且不會對系統的效能和穩定性產生負面影響。
總的來說,通過新增請求下游系統切面來統計耗時情況是一種有效的方法,可以幫助我們更好地理解系統的效能狀況,並幫助我們及時發現和解決潛在的效能問題。
一個比較嚴重的問題,即 Log4J 1.x 的阻塞問題。總共有大約90多個執行緒在等待同一把鎖。
升級紀錄檔版本:為了解決這個問題,我們決定將應用程式的 Log4J 1.x 版本升級到 Log4J 2.x 版本。這樣做的目的是提升效能並解決阻塞問題。升級過程需要仔細考慮,以確保與現有程式碼和設定的相容性。
相容性問題:在進行升級之前,我們建議先進行全面的測試和驗證。確保新版本的Log4J能夠正常工作,並且不會引入新的問題或破壞現有的功能。同時,我們還需要修改應用程式的組態檔,以便與新版本的Log4J相容。
總結起來,通過將應用程式的Log4J版本升級到Log4J 2.x,我們期望能夠解決阻塞問題,提升效能,並避免在壓測過程中生成過多的執行緒和堆dump紀錄檔。升級前需要進行充分的測試和驗證,確保順利完成,並能夠正常執行。
在後續的優化過程中,我們還考慮了將請求下游系統的紀錄檔列印方式改為非同步的方式,以進一步提升效果。
通過將請求下游系統的紀錄檔列印操作改為非同步方式,我們能夠獲得更好的效能和效果。非同步列印可以避免阻塞主執行緒,並將紀錄檔操作放到後臺進行處理。這樣一來,主執行緒可以繼續執行其他任務,而無需等待紀錄檔列印完成。
這種改變能夠顯著提高系統的整體響應效能,特別是在高並行場景下。通過非同步列印紀錄檔,系統能夠更快地處理請求,並減少對下游系統的負載。
需要注意的是,非同步紀錄檔列印雖然能夠提升效能,但也需要綜合考慮紀錄檔的精確性和實時性。非同步列印可能會導致紀錄檔的輸出順序不再保證嚴格的按照時間順序。因此,在實施非同步列印之前,需要確保系統的紀錄檔需求與非同步列印的特性相匹配。
總之,通過將請求下游系統的紀錄檔改為非同步列印方式,我們期望進一步提升系統效能和效果。但在實施之前,需要仔細評估業務需求,並確保非同步列印的特性與紀錄檔需求相符。
為了針對業務的實際情況,我們可以客製化一套超時引數,針對Http的工具類進行優化。這樣可以儘量減少Http連線被長時間Hold住而不釋放的情況,同時在必要的情況下,可以對Http請求工具類進行嘗試次數的控制。
例如,可以設定連線超時時間,用於控制建立連線的最長等待時間;同時可以設定讀取超時時間,用於控制從連線中讀取資料的最長等待時間。這樣一來,即使在網路不穩定的情況下,我們也能夠及時釋放Http連線,並減少長時間的等待。
需要注意的是,超時引數的設定和嘗試次數的控制都需要在合理的範圍內進行。過長的超時時間和過多的重試次數可能會導致系統響應時間延長和資源浪費。因此,我們應該根據具體業務需求和效能測試結果來進行調整和優化。
資料庫方面的優化主要通過收集產線出問題時刻的資料庫指標以及其他相關資訊,可以對系統進行優化和改進。以下是一些建議的優化方法:
資料庫連線管理:通過監控資料庫的連線指標,如 max_used_connections,max_user_connections 和 max_connections,可以瞭解資料庫連線的使用情況。如果出現連線數達到或接近最大連線數的情況,可能說明系統存在連線洩露或者連線過多的問題。可以通過檢查程式碼或者調整連線池的設定來解決這些問題。
資料庫連線超時設定:監控資料庫連線超時時間也是非常重要的。
效能時序分析圖:通過分析資料庫範例前後幾個小時的時序分析圖,可以獲取更多有關資料庫的資訊。
通過分析這些資訊,可以找到潛在的優化點並進行相應的優化操作,從而提高資料庫的效能和穩定性。
除了以上的建議,還需要綜合考慮系統的整體架構和業務需求,進行細緻的調優工作。同時,也建議定期進行效能測試和監控,以及和開發團隊溝通合作,共同優化系統的效能和穩定性。
在進行壓力測試過程中,建議生成更多的 heap dump 檔案,然後使用 Eclipse 工具來分析其中存在的大物件。經過分析,如果沒有發現任何可疑的地方,可以通過反查程式碼來進一步排查問題。特別是在一些定時任務需要載入大量資料的地方,建議在使用完這些資料後,立即手動釋放資源,以便儘快讓垃圾回收器回收記憶體。
增加 heap dump 檔案數量:生成更多的 heap dump 檔案可以提供更詳細的記憶體快照,從而更好地瞭解記憶體中存在的物件和資料結構。這有助於發現潛在的記憶體漏失或大物件的問題。
使用專業的記憶體分析工具:除了 Eclipse,還可以考慮使用其他專業的記憶體分析工具,如 VisualVM、MAT(Memory Analyzer Tool)等。這些工具提供了更多的功能和分析選項,能夠更準確地檢測和定位問題。
定期檢查定時任務的程式碼:定時任務可能會在載入大量資料後沒有及時釋放資源,導致記憶體佔用過高。通過反查程式碼,特別關注定時任務中的資源釋放邏輯,並確保在使用完資料後手動釋放相應的資源。
記憶體回收機制優化:除了手動釋放資源,還可以考慮優化垃圾回收器的工作方式。根據具體情況,可以調整垃圾回收器的引數,如堆大小、年輕代和老年代的比例等,以提高記憶體回收的效率。
在一些後臺定時輪詢的任務中,有些任務需要通過for迴圈來處理一些任務,這個時候我們可以每回圈一次或者回圈數次之後通過呼叫Thead.sleep(xxx)休眠一下,
一是可以緩衝一下IO高密度的操作,還有就是讓出CPU時間片,讓有些緊急的任務可以優先獲取CPU執行權。
在這裡,我向大家推薦一本關於JVM優化和調優的實戰系列書籍,《深入淺出Java虛擬機器器 — JVM原理與實戰》。這本書是最新出版的,內容涵蓋了與我們當前工作和開發範例密切相關的技術和實戰案例。通過學習這本書,我們可以深入瞭解Java虛擬機器器的原理,並通過實踐掌握優化和調優的技巧。我誠摯地推薦這本書給大家,相信它將為我們的工作和技術發展帶來巨大的收益。希望大家能夠抽出時間多多學習一下這本寶貴的資料。
【噹噹-點選連結】【京東-點選連結】
下面的案例以及優化方案就是取自於本書的實戰內容介紹:
記憶體漏失問題解決範例 在這個案例中,我們將學習如何識別和解決記憶體漏失問題。通過深入瞭解Java虛擬機器器的記憶體管理機制,我們將使用工具和技巧來診斷和分析潛在的記憶體漏失原因,並提供相應的優化方案來解決這個問題。
垃圾回收優化範例 這個案例將帶領我們深入研究垃圾回收機制,並學習如何優化垃圾回收過程以提高應用程式的效能。我們將探討不同的垃圾回收演演算法和設定選項,並通過實踐來選擇和調整最適合應用程式的垃圾回收策略。
為了應對將來的高業務量,目前需要擴容伺服器,將2臺伺服器擴容至4臺伺服器,然後將伺服器由2核4G升級成為4核8G。因此在升級過程中對於引數的調整也存在了一定的迷惑期。
注意:在進行優化之前,請確保有充足的測試資料和監控紀錄檔,並在優化過程中對系統效能進行全面評估和驗證。
注意,上述建議是基於一般的指導原則,實際的優化策略還需要結合具體的系統環境和效能需求進行調整。同時,還應注意在調整引數之前進行充分的測試和評估,以確保對系統效能產生積極的影響。
-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
我們以JVM引數-Xms5m -Xmx5m -XX:+PrintGCDetails -XX:+UseSerialGC
為基礎案例進行分析和介紹說明。
我們選擇這些引數作為基礎案例,是因為它們代表了一種較小的記憶體設定,並且使用了Serial垃圾收集器。這將使我們能夠更清楚地展示記憶體管理和垃圾收集的工作原理。
首先,我們來解釋一下這些引數的含義:
[DefNew: 1855K->1855K(1856K), 0.0000148 secs][Tenured: 2815K->4095K(4096K),0.0134819 secs] 4671K
如果我們將收集器引數變為-XX:+UseParNewGC
,引數來調整垃圾收集器為ParNew。ParNew是一種並行垃圾收集器,它適用於多核系統,可以實現垃圾回收與應用程式並行進行,提高垃圾收集的效率
[ParNew: 1856K->1856K(1856K), 0.0000107 secs][Tenured: 2890K->4095K(4096K),
收集器引數變為-XX:+ UseParallelGC
或 UseParallelOldGC
。
收集器引數變為-XX:+UseParallelGC
,那麼這將啟用並行年輕代垃圾收集器。這個收集器使用多個執行緒並行地進行垃圾收集,以提高垃圾收集的效率。
收集器引數變為-XX:+UseParallelOldGC
,那麼這將啟用並行老年代垃圾收集器。該收集器與並行年輕代垃圾收集器相比,還會對老年代進行並行的垃圾收集。
[PSYoungGen: 1024K->1022K(1536K)] [ParOldGen: 3783K->3782K(4096K)] 4807K->4804K(5632K),
CMS 收集器和 G1 收集器會有明顯的相關字樣,其他與 GC 相關的引數偵錯跟蹤之
-verbose:gc -XX:+PrintGC
引數設定為-verbose:gc
和-XX:+PrintGC
,那麼它們會開啟垃圾收集的詳細輸出紀錄檔。
-verbose:gc
引數會在每次垃圾收集發生時輸出垃圾收集的相關資訊,包括收集器型別、收集前後的堆記憶體使用情況以及回收所花費的時間等。
-XX:+PrintGC
引數會列印更詳細的垃圾收集紀錄檔,包括每次垃圾收集的詳細資訊,例如每個記憶體區域的收集情況、物件分配和回收的數量、堆記憶體的使用情況等。
通過將這兩個引數組合使用,你可以獲得更全面的垃圾收集紀錄檔,以便進行效能分析和調優。
-XX:+PrintGCDetails, +XX:+PrintGCTimeStamps
如果你將引數設定為-XX:+PrintGCDetails
和-XX:+PrintGCTimeStamps
,那麼它們會進一步增加垃圾收集的輸出資訊。
-XX:+PrintGCDetails
引數會列印更詳細的垃圾收集資訊,包括每次垃圾收集的詳細統計資料,例如每個記憶體區域的收集情況、收集器的型別和行為、物件的分配和回收情況等。這個引數可以幫助你更深入地瞭解垃圾收集的過程和對應的資料。
-XX:+PrintGCTimeStamps
引數會將每次垃圾收集的時間戳列印出來,以便你可以精確地知道每次垃圾收集的發生時間。這個引數可以幫助你分析和比較不同垃圾收集事件之間的時間間隔,從而更好地瞭解垃圾收集的影響和效能表現。
綜合使用這兩個引數,你可以獲得更詳細和準確的垃圾收集資訊和時間戳記錄,以幫助你進行更深入的效能分析和調優。
應用場景: 將 gc 的紀錄檔獨立寫入紀錄檔檔案,將 GC 紀錄檔與系統業務紀錄檔進行了分離,方便開發人員進行追蹤分析。
當需要設定 gc 紀錄檔路徑時,可以使用引數 -Xlogger:logpath。例如,如果你希望將 gc.log 檔案儲存在當前目錄下的 log 目錄中,可以使用以下命令進行設定:-Xlogger:logpath=log/gc.log
。
這樣,垃圾收集器的紀錄檔輸出將被儲存在 log 目錄下的 gc.log 檔案中。這個設定可幫助你更好地管理和組織紀錄檔檔案,方便後續的分析和調優工作。
使用引數-XX:+PrintHeapAtGC
可以在每次垃圾回收前後列印Heap的使用情況。這個引數對於跟蹤和分析垃圾回收過程中的記憶體使用情況非常有幫助。通過檢視列印輸出的資訊,你可以獲得每次垃圾回收的前後Heap的大小、使用情況以及垃圾回收器的行為等相關資訊。
注意,使用該引數可能會對效能產生一定的影響,因為在每次垃圾回收時都會進行一次列印操作。所以,只有在需要詳細觀察記憶體使用情況時才建議使用該引數。
引數設定:-XX:+TraceClassLoading
應用場景:在系統控制檯資訊中檢視類載入的過程和具體類資訊,用於分析類的載入順序和是否可以進行精簡操作。
通過使用引數-XX:+TraceClassLoading
,你可以在系統控制檯中觀察到類的載入過程和相關的類資訊。這個引數對於偵錯和分析類載入的順序和載入的類的詳細資訊非常有幫助。
當你在控制檯中啟用了該引數後,系統會列印出每個類的載入過程,包括類的名稱、載入時機、載入的類載入器等。通過檢視這些資訊,你可以瞭解類的載入順序,並針對需要優化的類進行精簡操作。
注意,這個引數會在系統控制檯輸出大量的資訊,可能會影響應用程式的效能。因此,建議僅在需要詳細瞭解類載入過程時才使用該引數。
引數設定:-XX:-HeapDumpOnOutOfMemoryError
當Java程式發生記憶體溢位錯誤時,通常會導致程式無法繼續執行,並丟擲java.lang.OutOfMemoryError異常。開啟-XX:-HeapDumpOnOutOfMemoryError引數後,JVM會在發生異常時自動觸發並建立一個堆記憶體的快照檔案,該檔案可以用於後續的偵錯和分析。
具體使用方法是,在Java虛擬機器器的啟動引數中新增-XX:-HeapDumpOnOutOfMemoryError。這樣當出現記憶體溢位錯誤時,JVM會自動將堆記憶體快照輸出到一個dump.core檔案中。
注意,呈現java.lang.OutOfMemoryError異常的場景通常是非常嚴重的,而且可能導致Java應用無法正常執行。因此,在生產環境中,建議結合監控和告警系統,及時發現並解決記憶體溢位問題。
引數設定:-XX:HeapDumpPath=./java_pid
在Java應用程式執行過程中,使用該引數可以將堆記憶體的當前狀態以快照的形式儲存到指定的檔案中。這對於診斷記憶體漏失、分析記憶體使用情況以及偵錯記憶體相關的問題非常有用。
具體使用方法是,將-XX:HeapDumpPath=./java_pid
.hprof新增到Java虛擬機器器的啟動引數中。其中, 。為Java程序的程序ID,它會被替換為實際的程序ID
例如,如果Java程序的程序ID是12345,則設定引數為-XX:HeapDumpPath=./java_pid12345.hprof。
在壓測過程中,發現大量的TIME-WAIT的情況,於是根據實際調整系統的TCP引數,在高並行的場景中,TIME-WAIT雖然會峰值爬的很高,但是降下來的時間也是非常快的,主要是需要快速回收或者重用TCP連線。
TCP引數情況如下:
vim /etc/sysctl.conf
編輯檔案,加入以下內容,您所列出的TCP引數設定如下:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
這些引數設定可以在對抗DDoS攻擊、優化TCP連線的回收和重用過程中起到一定的作用。讓我為您解釋一下每個引數的作用:
net.ipv4.tcp_syncookies = 1
: 啟用SYN cookie防禦機制。當伺服器遭受SYN洪泛攻擊時,該機制能夠通過檢查TCP三次握手的SYN包中的cookie資訊,來判斷是否真正有合法的連線請求。這樣可以防止伺服器因為大量的偽造連線請求而耗盡資源。
net.ipv4.tcp_tw_reuse = 1
: 啟用TIME-WAIT狀態的快速重用。當此選項啟用時,新的連線可以重用之前處於TIME-WAIT狀態的通訊端資源。這有助於避免通訊端資源不足的問題。
net.ipv4.tcp_tw_recycle = 1
: 啟用TIME-WAIT狀態的快速回收。當此選項啟用時,在短時間內可以立即回收處於TIME-WAIT狀態的通訊端資源,以便更快地重用這些資源。然而,請注意,此選項在某些情況下可能會導致連線失敗,所以使用時需要謹慎評估。
net.ipv4.tcp_fin_timeout = 30
: 設定TCP連線的FIN-WAIT-2狀態的超時時間為30秒。當一端傳送了FIN訊號而另一端沒有立即響應時,連線會進入FIN-WAIT-2狀態。在此狀態下,如果沒有收到對方的響應,將根據該超時時間自動關閉連線。
然後執行 /sbin/sysctl -p
讓引數生效。
Tomcat中,可以通過檢視Connector和Executor的屬性值來了解和調整相關引數。下面是獲取Tomcat Connector和Executor屬性值的方法:
可以按照以下步驟來獲取相關屬性值:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
maxThreads="200"
acceptCount="100" />
在上面的設定中,maxThreads表示Tomcat最大執行緒數,acceptCount表示最大排隊數。可以根據需要調整這些值。請注意,在生產環境中,建議根據系統的需求和實際情況來確定這些引數的值。
類似地,可以找到Executor元素來獲取或調整執行緒池相關的屬性值。例如:
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="200" minSpareThreads="10"/>
在上述設定中,maxThreads表示最大執行緒數,minSpareThreads表示最小空閒執行緒數。
經過分析和調優,系統的應用效能得到了提升。在優化的過程中,我們建立了一套獨特的思考方式,當前的設定雖然不是完美的,但確實適合系統。
需要注意的是,以上資料僅供參考。如果有更好的方法或更優雅的調優方式,歡迎大家討論和分享。希望以上內容滿足您的要求。如有其他問題,請隨時提問。
本文來自部落格園,作者:洛神灬殤,轉載請註明原文連結:https://www.cnblogs.com/liboware/p/17520002.html,任何足夠先進的科技,都與魔法無異。