轉自:http://perthcharles.github.io/2015/11/10/wiki-netstat-proc/
netstat -st輸出的兩個重要信息來源分別是/proc/net/snmp和/proc/net/netstat
本文將分類整理這些counterd的含義以及一些注意事項。
在整理的過程中,發現Rover Yu前輩已經
對這些counter做過詳細的整理。關於Rover Yu前輩的整理請查看參考資料中的前三篇。
本着不重復造輪子的原則。本文將盡量遵循以下原則,以期從不同的角度呈現對這些counter的理解。
a. 分類整理:根據涉及的不同TCP細節,對counter做更細致的分類 b. 結合sysctl配置:強調sysctl配置與counter之間的關聯 c. 強調異常:哪些counter出現非零值,往往就意味着出現了值得關注的問題 d. 信息抽取: 如何從counter中獲取有價值的信息 e. 僅關注TCP相關計數器
計數器分類
類別 | 涉及counters |
---|---|
常量 | RtoAlgorithm、RtoMin、RtoMax、MaxConn |
建連統計 | ActiveOpens、PassiveOpens、AttemptFails、CurrEstab、EstabResets |
數據包統計 | InSegs、OutSegs、RetransSegs、InErrs、OutRsts、InCsumErrors、EmbryonicRsts |
syncookies功能 | SyncookiesSent、SyncookiesRecv、SyncookiesFailed |
TIME_WAIT回收 | TW、TWRecycled、TWKilled、TCPTimeWaitOverflow |
RTO次數 | TCPTimeouts、TCPSpuriousRTOs、TCPLossProbes、TCPLossProbeRecovery、 TCPRenoRecoveryFail、TCPSackRecoveryFail、 TCPRenoFailures、TCPSackFailures、 TCPLossFailures |
Retrans數量 | TCPFastRetrans、TCPForwardRetrans、 TCPSlowStartRetrans、TCPLostRetransmit、 TCPRetransFail |
FastOpen | TCPFastOpenActive、TCPFastOpenPassive、 TCPFastOpenPassiveFail、TCPFastOpenListenOverflow、 TCPFastOpenCookieReqd |
MD5 | TCPMD5NotFound、TCPMD5Unexpected |
DelayedACK | DelayedACKs、DelayedACKLocked、DelayedACKLost、 TCPSchedulerFailed |
DSACK | TCPDSACKOldSent、TCPDSACKOfoSent、 TCPDSACKRecv、TCPDSACKOfoRecv、 TCPDSACKIgnoredOld、TCPDSACKIgnoredNoUndo |
Reorder | TCPFACKReorder、TCPSACKReorder、 TCPRenoReorder、TCPTSReorder |
Recovery | TCPRenoRecovery、TCPSackRecovery、 TCPRenoRecoveryFail、TCPSackRecoveryFail |
Abort | TCPAbortOnData、TCPAbortOnClose、 TCPAbortOnMemory、TCPAbortOnTimeout、 TCPAbortOnLingerTCPAbortFailed |
|reset相關 | |
|內存prune | PruneCalled、RcvPruned、OfoPruned、
TCPMemoryPressures |
|PAWS相關 | PAWSPassive、PAWSActive、PAWSEstab |
|Listen相關 | ListenOverflows、ListenDrops |
|undo相關 | TCPFullUndo、TCPPartialUndo、
TCPDSACKUndo、TCPLossUndo |
|快速路徑與慢速路徑 | TCPHPHits、TCPHPHitsToUser、
TCPPureAcks、TCPHPAcks |
常量
這些常量是Linux3.10中的默認值,僅在升級了內核版本時才需要關心一下這些值的變化。
RtoAlgorithm: 默認為1,RTO算法與RFC2698一致 RtoMin: 默認值為HZ/5,即200ms RtoMax: 默認值為120HZ,即120s MaxConn: 協議棧本身並不會限制TCP連接總數,默認值為-1.
建連統計
這些統計值中,只有CurrEstab反應的是系統當前狀態,而其他值則是反應的歷史狀態
同時需要注意的是,這些計數器將ESTABLISHED和CLOSE-WAIT狀態都作為當前連接數。
可以這么理解:這兩個狀態都以為這local=>peer方向的連接未被關閉
ActiveOpens: 主動建連次數,CLOSE => SYN-SENT次數 PassiveOpens: 被動建連次數,RFC原意是LISTEN => SYN-RECV次數,但Linux選擇在三次握手成功后才加1 AttemptFails: 建連失敗次數 EstabResets: 連接被reset次數,ESTABLISHED => CLOSE次數 + CLOSE-WAIT => CLOSE次數 CurrEstab: 當前TCP連接數,ESTABLISHED個數 + CLOSE-WAIT個數
數據包統計
這些統計值也是歷史值,獨立的來看意義並不大。一般可統計一段時間內的變化,關注以下幾個指標
a. TCP層的重傳率: ΔRetransSegs / ΔOutSegs — 越小越好,如果超過20%(這個值根據實際情況而定)則應該引起注意
b. Reset發送頻率: ΔOutRsts / ΔOutSegs — 越小越好,一般應該在1%以內
c. 錯誤包占比: ΔInErrs / ΔInSegs — 越小越好,一般應該在1%以內,同時由checksum導致的問題包應該更低
InSegs: 收到的數據包個數,包括有錯誤的包個數 OutSegs: 發送的數據包個數 RetransSegs: 重傳的包個數 InErrs: 收到的有問題的包個數 OutRsts: 發送的帶reset標記的包個數 InCsumErrors: 收到的checksum有問題的包個數,InErrs中應該只有*小部分*屬於該類型 EmbryonicRsts: 在SYN-RECV狀態收到帶RST/SYN標記的包個數
syncookies功能
syncookies一般不會被觸發,只有在tcp_max_syn_backlog隊列被占滿時才會被觸發
因此SyncookiesSent和SyncookiesRecv一般應該是0。
但是SyncookiesFailed值即使syncookies機制沒有被觸發,也很可能不為0。
這是因為一個處於LISTEN狀態的socket收到一個不帶SYN標記的數據包時,就會調
用cookie_v4_check()嘗試驗證cookie信息。而如果驗證失敗,Failed次數就加1。
SyncookiesSent: 使用syncookie技術發送的syn/ack包個數 SyncookiesRecv 收到攜帶有效syncookie信息包個數 SyncookiesFailed 收到攜帶無效syncookie信息包個數
注: syncookies機制是為應對synflood攻擊而被提出來的。
TIME-WAIT回收
TIME-WAIT狀態是TCP協議狀態機中的重要一環,服務器設備一般都有非常多處於TIME-WAIT狀態的socket
如果是在主要提供HTTP服務的設備上,TW值應該接近TcpPassiveOpens值。
一般情況下,sysctl_tcp_tw_reuse和sysctl_tcp_tw_recycle都是不推薦開啟的。這里解釋了為什么。
所以TWKilled和TWRecycled都應該是0。
同時TCPTimeWaitOverflow也應該是0,否則就意味着內存使用方面出了大問題。
TW:
經過正常的TCP_TIMEWAIT_LEN(60s)結束TW狀態的socket數量
TWKilled:
經過更短的時間結束TW狀態的socket數量。
只有在net.ipv4.tcp_tw_recycle開啟時,調度TW timer時才可能用更短的timeout值。
TWRecycled:
Port從TIMEWAIT socket中復用的次數。
只有在sysctl_tcp_tw_reuse開啟時,才可能加1 郁悶的是上面兩個counter的命名與sysctl的命名真是超級不一致啊。囧... TCPTimeWaitOverflow: 如果沒有內存分配TIME-WAIT結構體,則加1
RTO次數
RTO超時對TCP性能的影響是巨大的,因此關心RTO超時的次數也非常必要。
當然3.10中的TLP機制能夠減少一定量的TCPTimeouts數,將其轉換為快速重傳。
關於TLP的原理部分,可參考我的這篇wiki。
TCPTimeouts: RTO timer第一次超時的次數,僅包含直接超時的情況 TCPSpuriousRTOs: 通過F-RTO機制發現的虛假超時個數 TCPLossProbes: Probe Timeout(PTO)導致發送Tail Loss Probe (TLP)包的次數 TCPLossProbeRecovery: 丟失包剛好被TLP探測包修復的次數 /* 由以下計數器可以看出,進入RTO被觸發時,TCP是可能處於多種不同狀態的 */ TCPRenoRecoveryFail: (也放到了Recovery類別) 先進入Recovery階段,然后又RTO的次數,對端不支持SACK選項 TCPSackRecoveryFail:(也放到了Recovery類別) 先進入Recovery階段,然后又RTO的次數,對端支持SACK選項 TCPRenoFailures: 先進TCP_CA_Disorder階段,然后又RTO超時的次數,對端不支持SACK選項 TCPSackFailures: 先進TCP_CA_Disorder階段,然后又RTO超時的次數,對端支持SACK選項 TCPLossFailures: 先進TCP_CA_Loss階段,然后又RTO超時的次數
Retrans數量
這些計數器統計的重傳包,都不是由於RTO超時導致進行的重傳
如果結合RetransSegs統計來看,如果這些非RTO導致的重傳占比較大的話,也算是不幸中的萬幸。
另外LostRetransmit的數量應該偏低比較好,重傳包如果都大量被丟棄,則真的要注意了。
TCPLostRetransmit: 丟失的重傳SBK數量,沒有TSO時,等於丟失的重傳包數量 TCPFastRetrans: 成功快速重傳的SKB數量 TCPForwardRetrans: 成功ForwardRetrans的SKB數量,Forward Retrans重傳的序號高於retransmit_high的數據 TODO: retransmit_high目前的理解是被標記為lost的SKB中,最大的end_seq值 TCPSlowStartRetrans: 成功在Loss狀態發送的重傳SKB數量,而且這里僅記錄非RTO超時進入Loss狀態下的重傳數量 目前找到的一種非RTO進入Loss狀態的情況就是:tcp_check_sack_reneging()函數發現 接收端違反(renege)了之前的SACK信息時,會進入Loss狀態 TCPRetransFail: 嘗試FastRetrans、ForwardRetrans、SlowStartRetrans重傳失敗的次數
FastOpen
TCP FastOpen(TFO)技術是Google提出來減少三次握手開銷的技術,
核心原理就是在第一次建連時server計算一個cookies發給client,之后client向
server再次發起建連請求時就可以攜帶cookies信息驗明正身。如果cookies驗證通過,
server可以不等三次握手的最后一個ACK包就將client放在SYN包里面的數據傳遞給application layer。
在3.10內核中,TFO由sysctl_tcp_fastopen開關控制,默認值為0(關閉)。
而且sysctl_tcp_fastopen目前也是推薦關閉的,因為網絡中有些middlebox會丟棄那些帶有不認識的option的SYN包.
所以正常情況下這些值也應該都是0,當然如果收到過某些不懷好意帶TFO cookies信息的SYN包,
TCPFastOpenPassive計數器就可能不為0。
TCPFastOpenActive: 發送的帶TFO cookie的SYN包個數 TCPFastOpenPassive: 收到的帶TFO cookie的SYN包個數 TCPFastOpenPassiveFail: 使用TFO技術建連失敗的次數 TCPFastOpenListenOverflow: TFO請求數超過listener queue設置的上限則加1 TCPFastOpenCookieReqd: 收到一個請求TFO cookies的SYN包時加1
MD5
TCP MD5 Signature選項是為提高BGP Session的安全性而提出的,詳見RFC 2385。
因此內核中是以編譯選項,而不是sysctl接口來配置是否使用該功能的。
如果內核編譯是的CONFIG_TCP_MD5SIG選項未配置,則不會支持TCPMD5Sig,下面兩個計數器也就只能是0
TCPMD5NotFound: 希望收到帶MD5選項的包,但是包里面沒有MD5選項 TCPMD5Unexpected: 不希望收到帶MD5選項的包,但是包里面有MD5選項
DelayedACK
DelayedACK是內核中默認支持的,但即使使用DelayedACKs,每收到兩個數據包也
必須發送一個ACK。所以DelayedACKs可以估算為發送出去的ACK數量的一半。
同時DelayedACKLocked反應的是應用與內核爭搶socket的次數,
如果占DelayedACKs比例過大可能就需要看看應用程序是否有問題了。
DelayedACKs: 嘗試發送delayed ack的次數,包括未成功發送的次數 DelayedACKLocked: 由於usr鎖住了sock,而無法發送delayed ack的次數 DelayedACKLost: TODO 暫時不理解准確含義 TCPSchedulerFailed: 如果在delay ack處理函數中發現prequeue還有數據,就加1。 數據放到prequeue,就是想user能盡快處理。如果任由數據, 則可能user行為調度效果不好 這個值應該非常接近於零才正常
DSACK
該類型計數器統計的是收/發DSACK信息次數。
DSACKOldSent + DSACKOfoSent可以當做是發送出的DSACK信息的次數,而且概率上來講
OldSent應該占比更大。
同理DSACKRecv的數量也應該遠多於DSACKOfoRecv的數量。
另外DSACK信息的發送是需要sysctl_tcp_dsack開啟的,如果發現sent兩個計數器為零,則要檢查一下了。
一般還是建議開啟dsack選項
TCPDSACKOldSent: 如果收到的重復數據包序號比rcv_nxt(接收端想收到的下一個序號)小,則增加oldsent TCPDSACKOfoSent: 如果收到的重復數據包序號比rcv_nxt大,則是一個亂序的重復數據包,增加ofosent TCPDSACKRecv: 收到的old dsack信息次數,判斷old的方法:dsack序號小於ACK號 TCPDSACKOfoRecv: 收到的Ofo dsack信息次數 TCPDSACKIgnoredOld: 當一個dsack block被判定為無效,且設置過undo_marker,則加1 TCPDSACKIgnoredNoUndo: 當一個dsack block被判定為無效,且未設置undo_marker,則加1
Reorder
當發現了需要更新某條TCP流的reordering值(亂序值)時,以下計數器可能被使用到。
不過下面四個計數器為互斥關系,最少見的應該是TCPRenoReorder,畢竟sack已經被
廣泛部署使用了。
TODO: 什么情況下能准確的判斷出要更新reorder值呢?
TCPTSReorder: 如果是被一個partial ack確認后需要更新reorder值,則加1 這個地方取個TS的名字,還真是費解。不知道是什么的縮寫表示了partial ack的含義。 TCPRenoReorder: 如果被不支持SACK的dupack確認后,需要更新reorder值,則加1 TCPFACKReorder: 如果在需要更新時判斷支持FACK,則加1 TCPSACKReorder: 如果僅支持SACK,則該計數器加1
關於partial ack的完整內容可參考RFC6582,這里摘要定義部分
In the case of multiple packets dropped from a single window of data, the first new information available to the sender comes when the sender receives an acknowledgment for the retransmitted packet (that is, the packet retransmitted when fast retransmit was first entered). If there is a single packet drop and no reordering, then the acknowledgment for this packet will acknowledge all of the packets transmitted before fast retransmit was entered. However, if there are multiple packet drops, then the acknowledgment for the retransmitted packet will acknowledge some but not all of the packets transmitted before the fast retransmit. We call this acknowledgment a partial acknowledgment.
Recovery
該類型計數器統計的進入快速重傳階段的總次數及失敗次數,失敗次數是指先進入了
recovery階段,然后有RTO超時了。Fast Recovery沒有成功。
首先由於SACK選項已經大面積使用,RenoRecovery的次數應該遠小於SackRecovery的次數
另外fail的次數應該比例較小才比較理想
TCPRenoRecovery: 進入Recovery階段的次數,對端不支持SACK選項 TCPSackRecovery: 進入Recovery階段的次數,對端支持SACK選項 TCPRenoRecoveryFail: (也放到了RTO次數類別) 先進入Recovery階段,然后又RTO的次數,對端不支持SACK選項 TCPSackRecoveryFail:(也放到了RTO次數類別) 先進入Recovery階段,然后又RTO的次數,對端支持SACK選項
Abort
abort本身是一種很嚴重的問題,因此是否有必要關心這些計數器
后三個計數器如果不為0,則往往意味着系統發生了較為嚴重的問題,需要格外注意
TCPAbortOnClose: 如果調用tcp_close()關閉socket時,recv buffer中還有數據,則加1 此時會主動發送一個reset包給對端 TCPAbortOnData: 如果在FIN_WAIT_1和FIN_WAIT_2狀態下收到后續數據,或TCP_LINGER2設置小於0,則計數器加1 TCPAbortOnTimeout: 因各種計時器(RTO/PTO/keepalive)的重傳次數超過上限,而關閉連接時,計數器加1 TCPAbortOnMemory: 如果orphan socket數量或者tcp_memory_allocated超過上限,則加1 一般值為0 TCPAbortOnLinger: tcp_close()中,因tp->linger2被設置小於0,導致FIN_WAIT_2立即切換到CLOSE狀態的次數 一般值為0 TCPAbortFailed: 如果在准備發送reset時,分配SKB或者發送SKB失敗,則加1 一般值為0
c. 當rcv_buf不足時可能需要prune ofo queue, 這種情況就會導致PruneCalled計數器增加; 當一般都應該通過collapse節省內存就可以了,並不需要真正的prune掉被SACK的數據。 所以OfoPruned和更嚴重的RcvPruned都應該計數為0。
參考資料
TCP SNMP counters一
TCP SNMP counters二
TCP SNMP counters三
RFC 2012: SNMPv2 Management Information Base for the Transmission Control Protocol using SMIv2
TCP Fast Open: expediting web services