如何分析常见的TCP问题?
原文:https://time.geekbang.org/column/article/289896
對互聯(lián)網(wǎng)服務(wù)而言, 網(wǎng)絡(luò)問題是非常多的,而且很多問題的外在表現(xiàn)都是網(wǎng)絡(luò)問題,這就需要我們從網(wǎng)絡(luò)入手,分析清楚根本原因是什么。而要分析各種各樣的網(wǎng)絡(luò)問題,你必須掌握一些分析手段,這樣在出現(xiàn)問題的時(shí)候,你就可以高效地找到原因。閱讀下文了解下 TCP 的常見問題,以及對應(yīng)的分析套路。
在 Linux 上檢查網(wǎng)絡(luò)的常用工具
當(dāng)服務(wù)器產(chǎn)生問題,而我們又不清楚問題和什么有關(guān)時(shí),就需要運(yùn)行一些工具來檢查系統(tǒng)的整體狀況。其中,dstat 是我們常用的一種檢查工具:
$ dstat --total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system-- usr sys idl wai stl| read writ| recv send| in out | int csw 8 1 91 0 0| 0 4096B|7492B 7757B| 0 0 |4029 7399 8 1 91 0 0| 0 0 |7245B 7276B| 0 0 |4049 6967 8 1 91 0 0| 0 144k|7148B 7386B| 0 0 |3896 6971 9 2 89 0 0| 0 0 |7397B 7285B| 0 0 |4611 7426 8 1 91 0 0| 0 0 |7294B 7258B| 0 0 |3976 7062如上所示,dstat 會顯示四類系統(tǒng)資源的整體使用情況和兩個(gè)關(guān)鍵的系統(tǒng)指標(biāo)。這四類系統(tǒng)資源分別是:CPU、磁盤 I/O、 網(wǎng)絡(luò)和內(nèi)存。兩個(gè)關(guān)鍵的系統(tǒng)指標(biāo)是中斷次數(shù)(int)和上下文切換次數(shù)(csw)。而每個(gè)系統(tǒng)資源又會輸出它的一些關(guān)鍵指標(biāo),這里你需要注意以下幾點(diǎn):
如果你發(fā)現(xiàn)某一類系統(tǒng)資源對應(yīng)的指標(biāo)比較高,你就需要進(jìn)一步針對該系統(tǒng)資源做更深入的分析。假設(shè)你發(fā)現(xiàn)網(wǎng)絡(luò)吞吐比較高,那就繼續(xù)觀察網(wǎng)絡(luò)的相關(guān)指標(biāo),你可以用 dstat -h 來查看,比如針對 TCP,就可以使用 dstat -tcp:
$ dstat lis act syn tim clo 27 38 0 0 0 27 38 0 0 0它會統(tǒng)計(jì)并顯示系統(tǒng)中所有的 TCP 連接狀態(tài),這些指標(biāo)的含義如下:
在得到了 TCP 連接的整體狀況后,如果你想要看 TCP 連接的詳細(xì)信息,你可以使用 ss 這個(gè)命令來繼續(xù)觀察。通過 ss 你可以查看到每個(gè) TCP 連接都是什么樣的:
$ ss -natp State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN0 100 0.0.0.0:36457 0.0.0.0:* users:(("test",pid=11307,fd=17)) LISTEN0 5 0.0.0.0:33811 0.0.0.0:* users:(("test",pid=11307,fd=19)) ESTAB 0 0 127.0.0.1:57396 127.0.1.1:34751 users:(("test",pid=11307,fd=106)) ESTAB 0 0 127.0.0.1:57384 127.0.1.1:34751 users:(("test",pid=11307,fd=100))如上所示,我們能查看到每個(gè) TCP 連接的狀態(tài)(State)、接收隊(duì)列大小(Recv-Q)、發(fā)送隊(duì)列大小(Send-Q)、本地 IP 和端口(Local Address:Port )、遠(yuǎn)端 IP 和端口(Peer Address:Port)以及打開該 TCP 連接的進(jìn)程信息。
除了 ss 命令外,你也可以使用 netstat 命令來查看所有 TCP 連接的詳細(xì)信息:
不過,我不建議你使用 netstat,最好還是用 ss。因?yàn)?netstat 不僅比 ss 慢,而且開銷也大。netstat 是通過直接讀取 /proc/net/ 下面的文件來解析網(wǎng)絡(luò)連接信息的;而 ss 使用的是 netlink 方式,這種方式的效率會高很多。
netlink 在解析時(shí)會依賴內(nèi)核的一些診斷模塊,比如解析 TCP 信息就需要 tcp_diag 這個(gè)診斷模塊。如果診斷模塊不存在,那么 ss 就無法使用 netlink 這種方式了,這個(gè)時(shí)候它就會退化到和 netstat 一樣,也就是使用解析 /proc/net/ 這種方式,當(dāng)然了,它的效率也會相應(yīng)變差。
另外,如果你去看 netstat 手冊,通過 man netstat,你會發(fā)現(xiàn)這樣一句話“This program is obsolete. Replacement for netstat is ss”。所以,以后在分析網(wǎng)絡(luò)連接問題時(shí),我們盡量還是使用 ss,而不是 netstat。
netstat 屬于 net-tools 這個(gè)比較古老的工具集,而 ss 屬于 iproute2 這個(gè)工具集。net-tools 中的常用命令,幾乎都可以用 iproute2 中的新命令來代替,比如:
除了查看系統(tǒng)中的網(wǎng)絡(luò)連接信息外,我們有時(shí)候還需要去查看系統(tǒng)的網(wǎng)絡(luò)狀態(tài),比如說系統(tǒng)中是否存在丟包,以及是什么原因引起了丟包,這時(shí)候我們就需要 netstat -s 或者它的替代工具 nstat 了:
$ nstat -z | grep -i drop TcpExtLockDroppedIcmps 0 0.0 TcpExtListenDrops 0 0.0 TcpExtTCPBacklogDrop 0 0.0 TcpExtPFMemallocDrop 0 0.0 TcpExtTCPMinTTLDrop 0 0.0 TcpExtTCPDeferAcceptDrop 0 0.0 TcpExtTCPReqQFullDrop 0 0.0 TcpExtTCPOFODrop 0 0.0 TcpExtTCPZeroWindowDrop 0 0.0 TcpExtTCPRcvQDrop 0 0.0上面輸出的這些信息就包括了常見的丟包原因,因?yàn)槲业倪@臺主機(jī)很穩(wěn)定,所以你可以看到輸出的結(jié)果都是 0。
假如你通過這些常規(guī)檢查手段沒有發(fā)現(xiàn)異常,那你就需要考慮使用網(wǎng)絡(luò)分析的必備工具——tcpdump 了。
分析網(wǎng)絡(luò)問題你必須要掌握的工具:tcpdump
tcpdump 的使用技巧有很多,在這里我們不講述這些使用技巧,而是講述一下它的工作原理,以便于你理解 tcpdump 到底在干什么,以及它能夠分析什么樣的問題。
tcpdump 的大致原理如下圖所示:
tcpdump基本原理
tcpdump 抓包使用的是 libpacp 這種機(jī)制。它的大致原理是:在收發(fā)包時(shí),如果該包符合 tcpdump 設(shè)置的規(guī)則(BPF filter),那么該網(wǎng)絡(luò)包就會被拷貝一份到 tcpdump 的內(nèi)核緩沖區(qū),然后以 PACKET_MMAP 的方式將這部分內(nèi)存映射到 tcpdump 用戶空間,解析后就會把這些內(nèi)容給輸出了。
通過上圖你也可以看到,在收包的時(shí)候,如果網(wǎng)絡(luò)包已經(jīng)被網(wǎng)卡丟棄了,那么 tcpdump 是抓不到它的;在發(fā)包的時(shí)候,如果網(wǎng)絡(luò)包在協(xié)議棧里被丟棄了,比如因?yàn)榘l(fā)送緩沖區(qū)滿而被丟棄,tcpdump 同樣抓不到它。我們可以將 tcpdump 的能力范圍簡單地總結(jié)為:網(wǎng)卡以內(nèi)的問題可以交給 tcpdump 來處理;對于網(wǎng)卡以外(包括網(wǎng)卡上)的問題,tcpdump 可能就捉襟見肘了。這個(gè)時(shí)候,你需要在對端也使用 tcpdump 來抓包。
你還需要知道一點(diǎn),那就是 tcpdump 的開銷比較大,這主要在于 BPF 過濾器。如果系統(tǒng)中存在非常多的 TCP 連接,那么這個(gè)過濾的過程是非常耗時(shí)的,所以在生產(chǎn)環(huán)境中要慎用。但是,在出現(xiàn)網(wǎng)絡(luò)問題時(shí),如果你真的沒有什么排查思路,那就想辦法使用 tcpdump 來抓一下包吧,也許它的輸出會給你帶來一些意外的驚喜。
如果生產(chǎn)環(huán)境上運(yùn)行著很重要的業(yè)務(wù),你不敢使用 tcpdump 來抓包,那你就得去研究一些更加輕量級的追蹤方式了。接下來,我給你推薦的輕量級追蹤方式是 TCP Tracepoints。
TCP 疑難問題的輕量級分析手段:TCP Tracepoints
Tracepoint 是我分析問題常用的手段之一,在遇到一些疑難問題時(shí),我通常都會把一些相關(guān)的 Tracepoint 打開,把 Tracepoint 輸出的內(nèi)容保存起來,然后再在線下環(huán)境中分析。通常,我會寫一些 Python 腳本來分析這些內(nèi)容,畢竟 Python 在數(shù)據(jù)分析上還是很方便的。
對于 TCP 的相關(guān)問題,我也習(xí)慣使用這些 TCP Tracepoints 來分析問題。要想使用這些 Tracepoints,你的內(nèi)核版本需要為 4.16 及以上。這些常用的 TCP Tracepoints 路徑位于 /sys/kernel/debug/tracing/events/tcp/ 和 /sys/kernel/debug/tracing/events/sock/,它們的作用如下表所示:
我們回到 TCP Tracepoints 這一輕量級的追蹤方式。有一篇文章對它講解得很好,就是 Brendan Gregg 寫的TCP Tracepoints,這里面還詳細(xì)介紹了基于 Tracepoints 的一些工具,如果你覺得用 Python 腳本解析 TCP Tracepoints 的輸出有點(diǎn)麻煩,你可以直接使用里面推薦的那些工具。不過,你需要注意的是,這些工具都是基于 ebpf 來實(shí)現(xiàn)的,而 ebpf 有一個(gè)缺點(diǎn),就是它在加載的時(shí)候 CPU 開銷有些大。這是因?yàn)橛幸恍┚幾g工作比較消耗 CPU,所以你在使用這些命令時(shí)要先看下你的系統(tǒng) CPU 使用情況。當(dāng) ebpf 加載起來后,CPU 開銷就很小了,大致在 1% 以內(nèi)。在停止 ebpf 工具的追蹤時(shí),也會有一些 CPU 開銷,不過這個(gè)開銷比加載時(shí)消耗的要小很多,但是你同樣需要注意一下,以免影響到業(yè)務(wù)。
相比于 tcpdump 的臃腫,這些 TCP Tracepoints 就很輕量級了,你有必要用一用它們。
總結(jié)
我們講了 TCP 問題分析的慣用套路:
盡量不要使用 netstat 命令,而是多使用它的替代品 ss,因?yàn)?ss 的性能開銷更小,運(yùn)行也更快;
當(dāng)你面對網(wǎng)絡(luò)問題一籌莫展時(shí),可以考慮使用 tcpdump 抓包看看,當(dāng)系統(tǒng)中的網(wǎng)絡(luò)連接數(shù)較大時(shí),它對系統(tǒng)性能會產(chǎn)生比較明顯的影響,所以你需要想辦法避免它給業(yè)務(wù)帶來實(shí)質(zhì)影響;
TCP Tracepoints 是比較輕量級的分析方案,你需要去了解它們,最好試著去用一下它們。
請問 tcpdump 在解析內(nèi)核緩沖區(qū)里的數(shù)據(jù)時(shí),為什么使用 PACKET_MMAP 這種方式?你了解這種方式嗎?這樣做的好處是什么?歡迎你在留言區(qū)與我討論。
- END -
看完一鍵三連在看,轉(zhuǎn)發(fā),點(diǎn)贊
是對文章最大的贊賞,極客重生感謝你
推薦閱讀
圖解Linux 內(nèi)核TCP/IP 協(xié)議棧實(shí)現(xiàn)|Linux網(wǎng)絡(luò)硬核系列
網(wǎng)絡(luò)排障全景指南手冊v1.0精簡版pdf
一個(gè)奇葩的網(wǎng)絡(luò)問題
超強(qiáng)干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生總結(jié)
以上是生活随笔為你收集整理的如何分析常见的TCP问题?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入理解Linux socket
- 下一篇: 技术人的七夕表白可以有多浪漫?