後臺常見問題定位及應對指南
目錄
前言
常規錯誤
短連接之禍
IO之禍
總結
說明
由於個人水平有限,總結歸納的時候可能存在錯誤,還望指出。
前言
後臺故障是一個很寬泛的概念,本文有些標題黨了,本文只是針對如下幾點簡單分析
- 日誌規範
- tcp短連接使用過多
- io頻繁
程序邏輯錯誤或是發布變更引起的故障之類的不在討論範圍內。後臺服務出現故障時大多數情況下都會伴隨著cpu爆滿,或者內存不足,或者網卡塞滿,io頻繁等情況,故障的定位少不了神兵利器,這裏有一篇linux下常用工具的介紹:後臺故障&性能分析常用工具。
常規錯誤
這裏把能通過日誌定位到的錯誤視為常規錯誤。比如說某個調用失敗會導致該次請求失敗,我們可以通過寫日誌,將關鍵信息都記錄下來,方便之後的問題定位。寫日誌其實也有一些要註意的點
- 避免無效的信息,控制好日誌的量和級別,日誌寫多了影響性能
- 關鍵信息要記錄全,如某個調用失敗了,不能只打印一句 xxx Fail,而是要把對應的錯誤碼,錯誤信息,該調用的關鍵參數打印出來,方便後續問題定位。
短連接之禍
tcp連接在關閉的時候,主動關閉的一方將會經歷time_wait狀態,一旦端口消耗速度持續大於端口回收速度,自然會造成端口不夠用。但是話說回來,端口不夠用這種情況只會出現在主動發起連接的那一端,因為listen -> accept 並不需要分配端口。
定位方法
使用 ss -s 命令,查看各狀態的tcp連接數,如果time_wait狀態過多且端口消耗速度持續增長,就得留點神了
另外對於服務端來說,有時我們會想要定位連接主要來自哪些ip,可以通過ss配合awk及uniq,sort等命令得到結論,如:
ss -n |grep ESTAB | awk ‘{ print $5 }‘ | awk -F: ‘{ print $1 }‘ | sort | uniq -c | sort -rn
可以得到每個ip的連接數的排序
應對方案
1 放開port range,既然端口不夠用,那麽我們就加大端口數,使用如下命令可以得到當前系統向外建立連接時可用的端口範圍
cat /proc/sys/net/ipv4/ip_local_port_range
通過如下指令可以設置端口範圍,如
echo "1024 61000" > /proc/sys/net/ipv4/ip_local_port_range
但是調整port range後可能會出現某些服務無法重啟,這是因為range調大之後,原先的服務監聽的端口被系統分配出去了,這個時候可以把相關服務所綁定的端口設置到保留端口中,如
echo "10000,20000" > /proc/sys/net/ipv4/ip_local_reserved_ports
2 加快time_wait回收速度
通過如下命令可以打開time_wait快速回收,recycle需要配合timestapms一起使用,不過timestamps是默認就打開的,開啟後在3.5*RTO時間內回收echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle 若timestapms關閉了,則將其打開 echo "1" > /proc/sys/net/ipv4/tcp_timestamps
3 可以打開tcp_tw_resue選項,reuse也需要配合timestapms一起使用,開啟後在1s內回收
echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
註意: 以上的修改都是臨時的,一旦系統重啟又將恢復為默認值,可以通過將這些參數添加到/etc/sysctl.conf文件中,並使用sysctl –p命令使之生效。相關閱讀Linux之TCPIP內核參數優化,TCP連接的狀態與關閉方式,及其對Server與Client的影響,另外nat網絡下,打開tw_recycle將可能導致tcp連接建立錯誤,詳見鏈接tcp_tw_recycle和tcp_timestamps導致connect失敗問題,不過同idc內的服務器之間不存在這個問題,但是還有一個問題,timewait的存在幫我們規避掉了舊連接對新連接的影響,關閉之後,是可能導致舊連接的數據包或fin包到達新連接,或者主動關閉方發送的ack丟包,導致對端仍舊處於last_ack狀態,而主動關閉方快速回收了該socket,且新建連接時,該port被重用,發送syn過去時,將被回復rst,不過同idc內的網絡環境應該是非常良好的,dog微笑臉。最後還可以通過設置SO_LINGER選項,在關閉socket時會非常粗暴的直接發送一個rst報文給對端,從而避免掉timewait狀態。
- 4 使用長連接+連接池,引入長連接也有一些點需要註意,主要是以下三點
- 一是對底層服務的負載控制,短連接模式下可以很輕松的實現對底層服務的負載控制,長連接情況要麻煩一點
- 二是底層服務擴容時,連接池需要感知並調整
三是長連接+連接池技術 如果實現的不好的話本身也可能成為性能瓶頸,最好是能根據請求量動態的調整連接數,少了容易成為性能瓶頸,多了浪費端口,不過一般情況下端口肯定是夠用的。
IO之禍
這個沒什麽好說的,io多了必然給磁盤帶來壓力,由此帶來的io等待時間必然上漲,對於我們的後臺服務而言,io過多基本是由於寫日誌導致。
定位方法
使用vmstat 命令查看當前系統io情況,以及cpu的wa(cpu空轉等待io就緒)所占時間比例。如
vmstat 2
重點觀察bi,bo以及wa項。分別代表塊讀入速度和塊寫入速度以及io等待時間比例。
應對方法
通過/dev/null文件快速關閉日誌,如
ln -s /dev/null xxx.log
關於/dev/null和/dev/zero文件的介紹可以查看鏈接,/dev/null 和 /dev/zero 簡介及對比,關閉日誌只是緊急處理方法,後續還是要優化好寫日誌的邏輯,控制好量和級別。
總結
後臺服務出現性能故障時,可以遵循以下思路去定位(以下內容參考自客廳後臺開發群熊哥的聊天內容)
- 1 先看vmstat,看io是否高,如是,可關閉日誌,快速方法:ln -s /dev/null xxx.log
- 2 io不高,再看cpu消耗在用戶態還是內核態,如果是用戶態,通常是觸發了程序bug,可用ltrace定位,快速方法:重啟服務
- 3 如果內核態cpu高,對tcp類網絡服務,80%原因就是端口耗盡,通過ss -s看端口和time_wait等各個狀態,快速方法:加大port range,打開tw_recycle和tw_reuse
感謝運維們。
後臺常見問題定位及應對指南