45 | 答疑(五):网络收发过程中,缓冲区位置在哪里?
問題 1:網絡收發過程中緩沖區的位置
第一點,是網絡收發過程中,收發隊列和緩沖區位置的疑問。
在?關于 Linux 網絡,你必須要知道這些?中,我曾介紹過 Linux 網絡的收發流程。這個流程涉及到了多個隊列和緩沖區,包括:
- 網卡收發網絡包時,通過 DMA 方式交互的環形緩沖區;
- 網卡中斷處理程序為網絡幀分配的,內核數據結構?sk_buff 緩沖區;
- 應用程序通過套接字接口,與網絡協議棧交互時的套接字緩沖區。
不過相應的,就會有兩個問題。
首先,這些緩沖區的位置在哪兒?是在網卡硬件中,還是在內存中?這個問題其實仔細想一下,就很容易明白——這些緩沖區都處于內核管理的內存中。
其中,環形緩沖區,由于需要 DMA 與網卡交互,理應屬于網卡設備驅動的范圍。
sk_buff 緩沖區,是一個維護網絡幀結構的雙向鏈表,鏈表中的每一個元素都是一個網絡幀(Packet)。雖然 TCP/IP 協議棧分了好幾層,但上下不同層之間的傳遞,實際上只需要操作這個數據結構中的指針,而無需進行數據復制。
套接字緩沖區,則允許應用程序,給每個套接字配置不同大小的接收或發送緩沖區。應用程序發送數據,實際上就是將數據寫入緩沖區;而接收數據,其實就是從緩沖區中讀取。至于緩沖區中數據的進一步處理,則由傳輸層的 TCP 或 UDP 協議來完成。
其次,這些緩沖區,跟前面內存部分講到的 Buffer 和 Cache 有什么關聯嗎?
這個問題其實也不難回答。我在內存模塊曾提到過,內存中提到的 Buffer ,都跟塊設備直接相關;而其他的都是 Cache。
實際上,sk_buff、套接字緩沖、連接跟蹤等,都通過 slab 分配器來管理。你可以直接通過 /proc/slabinfo,來查看它們占用的內存大小。
問題 2:內核協議棧,是通過一個內核線程的方式來運行的嗎
第二個問題,內核協議棧的運行,是按照一個內核線程的方式嗎?在內核中,又是如何執行網絡協議棧的呢?
說到網絡收發,在中斷處理文章中我曾講過,其中的軟中斷處理,就有專門的內核線程 ksoftirqd。每個 CPU 都會綁定一個 ksoftirqd 內核線程,比如, 2 個 CPU 時,就會有 ksoftirqd/0 和 ksoftirqd/1 這兩個內核線程。
不過要注意,并非所有網絡功能,都在軟中斷內核線程中處理。內核中還有很多其他機制(比如硬中斷、kworker、slab 等),這些機制一起協同工作,才能保證整個網絡協議棧的正常運行。
關于內核中網絡協議棧的工作原理,以及如何動態跟蹤內核的執行流程,專欄后續還有專門的文章來講。如果對這部分感興趣,你可以先用我們提到過的 perf、systemtap、bcc-tools 等,試著來分析一下。
問題 3:最大連接數是不是受限于 65535 個端口
我們知道,無論 TCP 還是 UDP,端口號都只占 16 位,也就說其最大值也只有 65535。那是不是說,如果使用 TCP 協議,在單臺機器、單個 IP 地址時,并發連接數最大也只有 65535 呢?
對于這個問題,首先你要知道,Linux 協議棧,通過五元組來標志一個連接(即協議,源 IP、源端口、目的 IP、目的端口)。
明白了這一點,這個問題其實就有了思路。我們應該分客戶端和服務器端,這兩種場景來分析。
對客戶端來說,每次發起 TCP 連接請求時,都需要分配一個空閑的本地端口,去連接遠端的服務器。由于這個本地端口是獨占的,所以客戶端最多只能發起 65535 個連接。
對服務器端來說,其通常監聽在固定端口上(比如 80 端口),等待客戶端的連接。根據五元組結構,我們知道,客戶端的 IP 和端口都是可變的。如果不考慮 IP 地址分類以及資源限制,服務器端的理論最大連接數,可以達到 2 的 48 次方(IP 為 32 位,端口號為 16 位),遠大于 65535。
所以,綜合來看,客戶端最大支持 65535 個連接,而服務器端可支持的連接數是海量的。當然,由于 Linux 協議棧本身的性能,以及各種物理和軟件的資源限制等,這么大的連接數,還是遠遠達不到的(實際上,C10M 就已經很難了)。
問題 4: “如何優化 NAT 性能”課后思考
在?如何優化 NAT 性能?的最后, 我給你留了兩個思考題。
MASQUERADE 是最常用的 SNAT 規則之一,通常用來為多個內網 IP 地址,提供共享的出口 IP。假設現在有一臺 Linux 服務器,用了 MASQUERADE 方式,為內網所有 IP 提供出口訪問功能。那么,
- 當多個內網 IP 地址的端口號相同時,MASQUERADE 還能正常工作嗎?
- 內網 IP 地址數量或者請求數比較多的時候,這種使用方式有沒有什么潛在問題呢?
對于這兩個思考題,我來也、ninuxer 等同學,都給出了不錯的答案:
先看第一點,當多個內網 IP 地址的端口號相同時,MASQUERADE 當然仍可以正常工作。不過,你肯定也聽說過,配置 MASQUERADE 后,需要各個應用程序去手動配置修改端口號。
實際上,MASQUERADE 通過 conntrack 機制,記錄了每個連接的信息。而在剛才第三個問題 中,我提到過,標志一個連接需要五元組,只要這五元組不是同時相同,網絡連接就可以正常進行。
再看第二點,在內網 IP 地址和連接數比較小時,這種方式的問題不大。但在 IP 地址或并發連接數特別大的情況下,就可能碰到各種各樣的資源限制。
比如,MASQUERADE 既然把內部多個 IP ,轉換成了相同的外網 IP(即 SNAT),那么,為了確保發送出去的源端口不重復,原來網絡包的源端口也可能會被重新分配。這樣的話,轉換后的外網 IP 的端口號,就成了限制連接數的一個重要因素。
除此之外,連接跟蹤、MASQUERADE 機器的網絡帶寬等,都是潛在的瓶頸,并且還存在單點的問題。這些情況,在我們實際使用中都需要特別注意。
總結
以上是生活随笔為你收集整理的45 | 答疑(五):网络收发过程中,缓冲区位置在哪里?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 44 | 套路篇:网络性能优化的几个思路
- 下一篇: 26 | 案例篇:如何找出狂打日志的“内