大家好,這裡是「聊聊系統優化 」,併在下列地址同步更新 博客園:http://www.cnblogs.com/changsong/ 知乎專欄:https://zhuanlan.zhihu.com/youhua 思否專欄:https://segmentfault.com/blog/youhua 全網私 ...
大家好,這裡是「聊聊系統優化 」,併在下列地址同步更新
- 博客園:http://www.cnblogs.com/changsong/
- 知乎專欄:https://zhuanlan.zhihu.com/youhua
- 思否專欄:https://segmentfault.com/blog/youhua
- 全網私活,免費訂閱: http://www.zsihuo.com
在這裡我會從基於J2EE系統及互聯網架構方面,來談談系統優化的各個方面,乾貨滿滿,歡迎訂閱及關註!
前言
在上一期Tomcat優化中,針對JVM相關主要參數做過一定說明,這一期主要介紹進行一些概念及經驗。後面分章節去講述相關工具的基本使用。
優化優先順序
整體來講,系統優化應先優化架構及代碼,來解決具體功能點效率問題。最後通過JVM監控工具來發現一些隱藏較為深入的問題。
相關情形
- 記憶體占用並不斷增加, 系統壓力大情況下Full GC頻繁,系統出現卡頓
- 線程出現大量等待及死鎖, CPU使用率過高, 系統響應慢
- 堆(heap)記憶體不足或類載入導致JVM Crash,系統宕機
出現以上情況,就得使用工具分析JVM來確定問題
JVM記憶體模型
JDK1.7及以下
JDK1.8下,PermGen替換成Vm MetaSpace
Heap域
- 全局被所有線程分享
- 存所有對象及集合對象
方法域
- 全局被所有線程分享
- 存所有類的結構定義包含屬性,方法及構造函數等
Thread1.N
- 本地私有棧,一個線程一個棧
- 保持著所有在Heap域的對象引用(4byte長度)
- 存儲本地局部變數的存儲(基礎數據類型),程式運行狀態,方法返回值
記憶體泄漏的分類
- 堆記憶體泄漏 - 比較常見
- 持久代記憶體泄漏
- 棧記憶體泄漏
- 系統資源記憶體泄漏 -比較常見
線程相關知識
JVM線程狀態遷移
線程狀態
- 初始化(New):初期創建,啟動後則進入可執行狀態
- 可執行狀態(Runnable): 只要獲取CPU時間,則開始執行
- 運行狀態(Running): 正在使用CPU執行
-
阻塞狀態(Bloked)
- 等待阻塞(wait)
- 同步阻塞(synchronized)
- 睡眠阻塞(sleep)
- Join阻塞: 等待join子線程結束後,主線程才能執行,將非同步執行的線程合併為同步的線程
- 結束狀態: 線程執行完畢或者異常退出
性能監控關註點
- 系統線程總數
- 死鎖線程 需要優先解決
-
線程Bloked總數數量
線程Bloked多的情況下,考慮對待處理數據進行分片,進行多通道,多線程處理提高系統性能
如果系統處理慢,但CPU占用一直很低,就需要梳理系統處理流程,串列處理該並行處理,並行處理流程提高併發來解決。
線程死鎖
當兩個或者多個線程嘗試獲取其他資源的鎖,而每個線程又陷入無限等待其他資源鎖的釋放(相互等待),除非一個用戶的進程被終止。
幾個死鎖場景
- 兩個線程相互調用Thread.join(), 導致互相等待同步結束。
慎用線程join操作
- 當兩個線程使用嵌套的同步塊時,一個線程占用了另一個線程的必需的鎖,互相等待時被阻塞,就有可能出現死鎖。 也可能多個線程形成環狀鎖,比如線程A等待線程B,線程B等待線程C,線程C等待線程A。線程A為了檢測死鎖,它需要遞進地檢測所有被B請求的鎖。從線程B所請求的鎖開始,線程A找到了線程C,發現線程C請求的鎖被線程A自己持有著。這是它就知道發生了死鎖。
- MySql死鎖
MySql中兩個線程同時對兩條記錄做先讀後寫操作
避免死鎖
- 安全狀態
找到一個分配資源的序列能讓所有進程都順利完成
- 銀行家演算法
採用預分配策略檢查分配完成時系統是否處在安全狀態
檢測死鎖
- VisualVM(或其他工具)
監控線程狀態,如果出現死鎖得到相關代碼位置
- 死鎖定理化間資源分配圖
利用死鎖定理化間資源分配圖來分析死鎖的存在
參見以下資料:
https://www.coursera.org/lect...
總結
本章主要講了一些核心知識,主要為了讓大家瞭解系統優化到底優化和解決什麼問題,什麼是優化的目標。後續章節會講到tomcat的JMX配置,VisualVM,Tprofile等工具的使用。
思考題
JVM線程有哪些狀態,這些線程大多處於什麼樣的狀態分佈, 我們可以稱系統運行是健康的。