大家好,我是飛哥!
前段時間飛哥參加了一期 OSChina 官方舉辦的「高手問答」欄目。在這個欄目里,我和 OSChina 的網友們以《深入理解 Linux 網絡》為主題,對大家日常所關心的一些問題展開了一些技術探討。
問:一個 linux 最多能 65535 個端口,那麼在虛擬化盛行的現在,這個 65535 更容易被占滿了吧,怎麼處理?
答:首先一個 linux 最多能 65535 個端口的說法是不確切的。因為即使在一台 Linux 上也是可以配置多 ip 的,每個 ip 都可以有 65535個 端口可用。
另外再說說現代的虛擬化。在 2008 年發布的 Linux2.6.24 內核版本里,引入了一個叫網絡命名空間的東東。這個就是現代容器虛擬化的基石。在每一個命名空間裡,都可以擁有自己獨立的 ip、端口號、路由表等等網絡資源。對於現在常用的 docker ,一個 docker 里就對應一個網絡命名空間(非host模式下)。每個容器都是 65536 個端口可用的。
另外還有一個要知道的是,如果連接不同的服務器端的時候,即使只有一個 ip,同一個端口號也是可以用於連接不同的服務端的。所以不要擔心 65535 的限制。
問題2:訪問本機的 ip 會通過交換機或者路由器嗎?問:ip 填寫自己本機的 ip 會通過交換機或者路由器嗎。
答:不會的,你可以試試,無論是使用本機 ip,還是 127.0.0.1 都是只過迴環設備 lo。通過在 lo 上抓包即可看到,而在真正的物理網卡下是抓不到包的。
問題3:服務器端只有一個端口,收發請求不會亂嗎?問:老師我本來沒覺得我不明白 但是看了上面 列舉的問題 <一台機器最多能支持多少條 TCP 連接>就有點疑惑了 就是服務器作為接收 WEB 或者其他端請求時 不管是 80 還是 443, 對外暴露的基本上是一樣的端口,http請求來了之後 請求之間不會相互干擾嗎?或者同一個端口可以有多少個http請求,我自己都凌亂了,謝謝老師!
答:我們分三步來理解你說的問題。
第一、服務器端在接收到新連接的時候會創建新的 socket 出來。這個新的socket 上有完整的四元組(內部源 IP、源端口、目的 IP 和目的端口)信息,並以 hashtable 的方式管理。
第二、TCP 網絡包體內部源 IP、源端口、目的 IP 和目的端口等信息都是攜帶在包頭裡的。
第三。內核在接收到網絡包的時候,在協議棧處理的時候會解析包頭,根據這個包頭中完整的四元組和內核中 hashtable 中管理的 socket 進行匹配,只有四元組信息完全一致,才能把接收到的數據放到該 socket 的接收隊列中。不同的請求的 socket 上四元組信息並不完全一致,所以請求之間不會相互干擾。
問題4:網上著名的 C10K 並發連接問題 具體是怎麼回事?問:網上著名的 C10K 並發連接問題 具體是怎麼回事?
答:C10K 問題算是歷史上的一個問題,在 Linux 上最早的開發模型里,只有線程編程模型,來一個用戶就需要使用一個進程來處理。但隨着互聯網發展的井噴,服務器端要支持的並發數越來越高。如果還繼續沿用這個模型的話,就需要投入巨量的服務器資源。所以 C10K 問題的提出,就是要處理如何讓一台服務器同時處理 1 萬個用戶連接請求。在 epoll 誕生以後,C10K 已經不是問題了。
問題5:網絡丟包該如何排查問:剛好遇到疑似 TCP 傳輸丟包的問題,想請教老師科普下這種問題排查的整體思路和順序是什麼
答:TCP 傳輸丟包問題使用 tcpdump 抓包看看,看看重試是如何發生的,使用 wireshark 打開,使用過濾器 tcp.analysis.retransmission 找到重傳的包。還有一個基於 eBPF 的輕量級工具 tcpretrans ,也可以試試。不過 eBPF 對 Linux 版本要求較高。
問題6:一台機器最多能支持多少條 TCP 連接?問:一台機器最多能支持多少條 TCP 連接? 這個公式是什麼?怎麼計算,64GB 的 Linux 服務器,可以支持多少條?
答:一台機器最多能支持多少條 TCP 連接。只說服務器端吧,一是受限於 Linux 里配置的可打開文件句柄數等內核參數,但這些都很好修改,調幾個參數就行了。二就是內存了,這個是硬性限制。最少也得是 3.3 KB 左右。所以如果算極限情況下的TCP連接數,64 GB 除以 3.3KB 就行了。但一般都會給收發緩存區以及其它應用留一些 buffer
問題7:一條 TCP 需要消耗多大的內存問:一條 TCP 連接需要消耗多大的內存 ,像mysql這種連接數,和用戶登錄這種 session 信息,也是一條 tcp 連接嗎?
答:TCP 連接在內核里消耗內存主要是兩塊,一是表示 TCP 連接的 socket,大約是 3.3K 左右。二是接收和發送數據的緩存區,這個可大可小,大了收發速度更快,小了更省內存。但在較新的版本里,只要收髮結束,內存就都可以回收了。你說的 mysql 的用戶登錄、session 等信息這個數據 TCP 里傳輸的數據。這個數據就看用戶進程里是怎麼存儲的了,如果存在內存里就占內存,存到磁盤裡就占磁盤。
問題8:CPU 飆高到 100%問:老師好,我的線上服務總是莫名其妙 CPU 飆高到 100%,然後到某一個時刻突然掉下來,內存和 IO 幾乎都正常值,請問應該從哪方面入手排查呢?
答:這個就得具體問題具體分析了。得看看是用戶態內存消耗的高,還是內核態消耗的高。相關的命令有 top、vmstat、sar、mpstat 等。如果是內核態就用 strace 命令統計一下系統調用的耗時情況,看有沒有耗時特別長的。還可以考慮使用 perf 火焰圖分析一下。
問題9:有沒有推薦網絡調優和監控的工具問:請問張老師, 有沒有推薦網絡調優和監控的工具。
答:網絡比較複雜,最好先了解它內部的工作原理,看一下《深入理解Linux網絡》,然後再找相應步驟的工具,可以看看《性能之巔》,這樣更好一些。
問題10:net.ipv4 有非常多的屬性,難道要挨個背下來?問:net.ipv4 有非常多的屬性,難道要挨個背下來?現在就處於不知道從何看起的階段,不知道直接看您的這本書是否能幫忙建立起知識結構,能知其然且知其所以然
答:不需要背,最重要的是要理解網絡工作底層工作原理,這樣再看這些參數的時候就非常容易理解了。這就好比庖丁解牛,你如果對牛的骨骼肌肉的內部原理理解非常透徹的時候,你解牛的時候自然就非常容易。而不是去死記硬背這些內核參數。
咱們《深入理解Linux網絡》就是這樣一本介紹網絡底層工作原理的書。書中會介紹到半連接隊列、全連接是如何工作的,理解這個原理你就能輕鬆理解 syncookie 這個參數了。而且再遭遇 TCP 中的三次握手等問題的時候,你也能快速排查和定位原因了。
問題11:線上被衝垮,幫忙 review 一下問:你好,曾經解決過一次線上服務器高峰時被衝垮的問題,原因是網絡相關,靠着搜索引擎解決了後還是處於知其然不知其所以然的情況,麻煩幫忙 review 下
首先高峰被衝垮,看了 mysql ,程序都沒異常,懷疑是網絡問題。然後 netstat -n | awk 統計各種tcp連接狀態的數量,發現別的都很少,established 單機上萬了,time_wait 也非常高。帶寬直接被打滿
然後修改 file-max 和 sysctl 配置了如下和一些其他屬性後,time_wait 瞬間下降。
net.ipv4.tcp_syncookies=1net.ipv4.tcp_tw_reuse=1net.ipv4.tcp_tw_recycle=1最後又加上 nginx ip 限流解決。雖然搜索到了生效的幾個 net.ipv4 配置的意思,但是依然不知道為什麼會有這麼多的 time_wait
答:你的問題的根本原因是在大流量(可能是攻擊流量)請求的情況下使用了短連接。每一個短連接的主動釋放連接的一方的 socket 都不會直接消失,而是會先釋放一部分內核對象後進入 TIME_WAIT 狀態,然後這個 socket 會一直占用一個端口號大約 2 分鐘左右。recycle 和 reuse 的共同的作用都是儘量減少 socket 在 TIME_WAIT 上呆的時間,這樣就能儘快釋放端口。儘快地退出 TIME_WAIT 可以釋放端口,保證後面的用戶來的時候,服務器請求如 mysql 等數據服務器的時候,可以有充足的端口可用。
問題12:Linux 網絡連接建立以後,在文件層發生的變化是什麼樣的?問:Linux 網絡連接建立以後,在文件層發生的變化是什麼樣的?都說linux中所有的東西是文件,我如何通過網絡連接去尋找該連接對應的文件?是一個文件還是多個文件?
答:linux一切皆是文件,說的其實是一個 struct file 結構體。磁盤上的文件,socket 都有這樣一個 struct file 對象,是一個內核上層的抽象。
但是在內核底層上磁盤文件、socket 還是完完全全不一樣的東西。cat命令也並不能把一個socket中的數據內容給展示出來。如果你非得想用類似 cat 的功能,linux 下有個 ncat 命令你可以玩玩。
服務器端
#ncat-v-lp8081Ncat:Version6.40(http://nmap.org/ncat)......helloworld客戶端
#nc-v127.0.0.18081Ncat:Version6.40(http://nmap.org/ncat)Ncat:Connectedto127.0.0.1:8081.helloworld問題13:有沒有通用的線上配置核心參數問:關於連接和性能瓶頸,線上我們經常是遇到問題再去搜方案,有沒有通用的必須要在線上配置的核心參數呢。答:通用的其實內核都已經用默認值的方式給弄好了。無奈業務之間差異太多,所以想一套參數適配所有的業務,基本上還是不可能的。還得靠工程師根據當前業務的特點來適當靈活調整。
想看這次活動的同學可以點擊左下角的「閱讀原文」!