問題定位追溯
準備方面
- 思路:撥開雲霧見天日,守得雲開見月明 --《送徵雁》
- 工具:工欲善其事,必先利其器 --《論語》
- 練習:無他,但手熟爾 --《賣油翁》
常見問題列表
- 服務報錯,返回服務器錯誤;
- 服務無法訪問;
- 服務很慢,很久才能返回結果;
- 數據接口並未按照預設的程序路徑執行;
處理思路
1. 服務報錯,返回服務器錯誤(Http-code爲500
);
分析:對於這種問題,屬於最基本的線上問題,一般常見於數據校驗缺失、程序邏輯問題、第三方依賴服務故障、網絡故障等問題觸發;
解決方法:(誰在什麼時間節點發起了什麼請求,命中了哪個程序路徑,引發了什麼錯誤)定位該請求的時間點,當時的請求參數和上下文信息,找到對應的堆棧,然後進行相應的排查;
常見診斷步驟:
- 通過IDE找到對應url的類名和方法名,比如通過
/order/addOrder.json
找到OrderInfoController.addOrder
; - 從sku.log(找對應的業務日誌,這裏以商品訂單爲例)找到當時的報錯堆棧,搜索
OrderInfoController.addOrder
,搜索命令爲grep 'OrderInfoController.addOrder' sku.log
或者通過elk
進行查找,這裏如果有多個過濾條件,可以使用linux管道,如查找方法名爲OrderInfoController.addOrder
且時間是2019-05-04 14:00:00
可以使用grep 'OrderInfoController.addOrder' sku.log | grep '2019-05-04 14:00:00'
; - 找到對應的日誌記錄行後,再去找出當時錯誤的具體原因,可以結合當時上下文信息來一起判斷,這裏可以通過線程號向上查詢得出上下文信息(因此方法中需要有必須的上下文信息打印纔可追溯,否則即使找到了堆棧,也需要靠推測和猜測);
2. 服務無法訪問
分析:需要理清從客戶端發起請求到服務端響應會經過哪些環節,是否其中某一個或者多個環節發生了問題;
解決方法:根據客戶端的顯示狀況和http狀態碼來區別分析;
從客戶端發起http請求到服務端響應一般需要經過的環節
- DNS域名解析:如果客戶端是用域名訪問,會做dns解析,得到ip;
- 建立TCP鏈接:通過第一步得到的ip和端口號(http默認是80,https默認是443),通過三次握手建立一條tcp鏈接;
- 傳輸數據(序列化和反序列化):客戶端按照http請求格式組裝請求,通過tcp鏈接傳輸到服務端;
- 代理服務器轉發:一般服務端都會有代理服務器,進行反向代理,將請求傳輸到業務服務器;
- 定製攔截鏈過濾:業務服務器會有一系列定製的攔截鏈進行攔截過濾,比如身份認證、權限校驗等;
- 業務處理:按照指定輸入,執行業務開發人員開發的業務邏輯,這個過程中,會與外部依賴服務和中間件進行數據交換,最終返回相應的數據;
常見診斷步驟:
- 瀏覽器顯示無法找到服務的ip地址、xxx的響應時間過長:域名問題|dns解析問題|vpn問題|端口權限問題;
- 服務502:應用服務器掛掉了,或者代理服務器認爲應用服務器掛掉了,那代理服務器什麼時候會認爲應用服務器掛掉呢,應用服務器什麼時候會掛掉呢?);
- 應用服務器確實掛掉了,進程不在(使用
ps -ef
或jps
或pgrep
均可); - 應用服務器和代理服務器網絡不通,無法建立鏈接(使用
ping
判斷配置的ip或域名是否可達); - 代理配置,nginx默認的proxy_next_stream功能,502和504都會認爲上游應用掛掉了(http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream);
- 應用服務器確實掛掉了,進程不在(使用
- 服務504:應用服務器響應超時,超過了代理服務配置的超時時間,應用處理慢的問題轉到問題3;
3. 服務很慢,很久才能返回結果
分析:服務很慢就是響應時間很長,響應時間的公式爲
網絡延遲+服務器處理延遲
:
- 其中
網絡延遲
是指建立網絡鏈接的延遲+一次請求往返的數據傳輸延遲
如果當時網絡不通會導致網絡鏈接建立的延遲變大,會導致網絡延遲
變大;
另外,如果上傳文件很大,上行帶寬較小 或者 下載文件很大,下行帶寬較小 也會導致網絡延遲
變大; - 其中
服務器處理延遲
是指請求到達指定web服務器和web服務器返回響應之間的延遲,這包含了web服務器和應用服務器的網絡延遲 + 應用服務器的處理延遲
;
一般情況下web服務器和應用服務器間的延遲
基本沒問題,因爲都處於內網,不過也存在web服務器處理忙導致的處理超時,web服務器需做好負載均衡和流量隔離;
應用服務器處理延遲
包含的問題則會五花八門,時間關係只會描述一些比較典型場景如慢sql、大sql
、CPU密集型接口,算法質量差,時間複雜度高
、IO密集型接口,且讀取效率不高
、存在內存泄露,時間久了越來越慢
、依賴服務處理慢
等等;
解決方法:首先需要定位出問題在什麼地方,這很依賴於系統和程序目前的狀態,以及一些必要的日誌,才能綜合分析到底是哪個環節或者哪些環節累加導致了最終的高處理延遲;
常見診斷步驟
- 查看系統負載是否很高,通過命令
w
和top
都可以看到load average
,如果load average
數值大於cpu核心數
,表示系統很多任務在排隊,流量較大,之前發生一起事故是運維將官網的代理和神農架代理放在一塊,代理服務器是2核,導致服務響應持續超時,這種最好是做流量隔離,避免關鍵服務受到影響; - 查看cpu佔用率是不是有異常情況,通過命令
top
可以看到cpu佔用率,如果cpu持續處於很高的佔用率,說明程序有哪些地方在做cpu密集型的操作,極有可能死循環,可以通過top -H -p pid
來定位到對應進程的各個線程信息,轉4; - 查看數據庫是不是有
sql
處於執行中,這種情況很多,可以通過show full processlist
來查看; - 查看是不是有線程一直處於運行態,通過命令
jstack -l pid
來查看; - 查看是不是有可能是一直在進行gc,通過命令
jstat -gcutil pid frequency times
來觀察;
常用工具及選項
grep
:使用該命令可以快速從文本中找出指定輸入的匹配行,輸入可以是原生字符串也可以是正則表達式;
常見選項:- -A:after,找出匹配行以及匹配行後指定數量的行;
- -B:before,找出匹配行以及匹配行後指定數量的行;
- -C:center,找出匹配行以及匹配行前後指定數量的行;
- -E:extended-regexp,使用正則表達式來做字符串匹配;
less
:使用該命令以緩衝式窗口的方式來訪問文本文件;
常見選項:- f:向前翻一頁;
- b:向後翻一頁;
- Enter:向前滾動一行;
- /:向下搜索"字符串";
- ?:向上搜索"字符串";
- n:對於/和?搜索命中的字符串,查找下一處命中的;
- N:對於/和?搜索命中的字符串,查找上一處命中的;
- q:退出瀏覽;
ping
:使用該命令來判斷網絡連通性;nc
或telnet
:通過該命令來判斷ip+端口是不是可達,一般使用nc -zv ip port
;jps
:查看java進程;jstack
:查看java線程堆棧,一般使用jstack -l
來查看線程列表和相應狀態;jstat
:查看java進程內存佔用率;
相關圖示
)
參閱
- https://mp.weixin.qq.com/s/AUST6fSc1zqeQ7rreC0gWA
- https://blog.csdn.net/GitChat/article/details/79019454
- https://docs.oracle.com/javase/8/docs/technotes/tools/index.html
- 《Java性能優化權威指南》
- http://nginx.org/en/docs/