摘要:中斷程序分配一個叫 sk_buff 的 socket buffer數據結構,拷貝網絡幀到這個結構,然後軟中斷通知內核來處理網絡幀了。XDP:在內核網絡協議棧前處理網絡包。

0x00 前言

在上篇學習筆記中我總結了 I/O 學習筆記,本篇會總結 Linux 網絡的性能優化學習筆記。在上篇文章中我們提到了說磁盤 I/O 就是計算機的最終數據持久化的地方,如下圖在馮諾依曼架構中也就是對應輸入輸出的設備,而存儲器則就是內存。

在單臺計算機的時候,可以說計算過程就是先從輸入設備獲取指令和數據,在經過運算器的處理後,最終將運算結果輸出到輸出設備上,而 I/O 的產生則是在和輸入和輸出設備打交道了。如果是多臺計算機,計算機之間如何互相溝通呢?那麼就需要通過網絡來連接各個計算機了。

在計算機之間的溝通,無非也就是指令和數據就是這兩種。比如我訪問一個 Web 網站,本質上不就是從網站服務器上獲取數據嗎?又比如在分佈式的計算集羣中,master 節點向 slave 節點下發計算任務,這就輸出指令呀。是不是感覺網絡和磁盤 I/O 很相似?沒錯,他們在馮諾依曼結果中都是作爲輸入輸出設備,所以他們有很多相似之處,比如在 Linux 系統中,網絡 I/O 的操作和文件操作很相似,但網絡的層次比文件系統 I/O 更多,所以會更加複雜,一篇文章無法概述,本筆記只是記錄一些要點。

0x01 網絡基礎

0x0100 收發流程

網絡和文件系統一樣,爲了解耦異構設備,都是分層的,分層在網絡中主要分爲 OSI 和 TCP/IP 模型。如下所示

而自然和磁盤一樣,Linux 內核在處理網絡包的時候對不同的層會進行不同的處理。

  • 應用層: 內核態系統調用,通過 socket 來發包
  • 傳輸層: 對應用層的包進行封裝,是五元組的抽象
  • IP層: IP 報文發送,路由
  • 鏈路層: 封幀,mac 尋址
  • 網卡驅動: 收發包,網卡驅動收發包會通過硬中斷和內核交互

0x0101 收包

  1. 網卡 DMA(可以理解爲直接讀 I/O 到內存,減少 cpu 的介入) 把收到的網絡幀放到收包隊列(在內存中),硬中斷通知中斷程序處理
  2. 中斷程序分配一個叫 sk_buff 的 socket buffer數據結構,拷貝網絡幀到這個結構,然後軟中斷通知內核來處理網絡幀了
  3. 內核獲得網絡幀後,就跟剝洋蔥一樣,一層層的剝開
    1. 數據鏈路層:檢查報文,去掉幀頭幀尾,看 ip 層是什麼報文,如果是 6 就交給上層 ipv6 對應的協議處理,如果是 4 就交給 4
    2. IP層: 判斷網絡包走向,是轉發還是交給上層處理。比如 iptable 中的 forward 鏈就是轉發鏈,如果要交給上層則確定上層協議是 tcp/udp 等,並去掉頭尾
    3. 傳輸層:根據 tcp/udp 頭,根據四元組找到對應的 socket,然後把數據拷貝到 socket 裏
    4. 應用層:操作 socket 讀取數據

0x0102 發包

  1. 應用層:通過系統調用,把數據包寫到 socket 裏
  2. 傳輸層:增加 tcp 頭
  3. ip 層:增加 ip 頭,路由尋址,找到下一跳,根據 MTU 分片
  4. 數據鏈路層:根據 mac 地址尋址,找到下一跳的 mac,增加頭尾,放到發包隊列,軟中斷通知中斷程序驅動
  5. 物理層:驅動程序 DMA 讀取網絡幀,通過物理網卡通過脈衝信號或光信號發包

0x0110 性能指標

  1. 帶寬: 最大傳輸速率
  2. 吞吐量: 單位時間內傳輸數據量
  3. 延時: 發出請求到收到響應的時間
  4. PPS: Packet Per Second,每秒發包量
  5. 網絡可用性
  6. 併發數
  7. 丟包率
  8. 重傳率

0x02 網絡 I/O 原理

I/O通知方式:

  1. 水平觸發: 應用程序 可以隨時讀fd
  2. 邊緣觸發: 只能在 fd 發生變化是纔可以讀

I/O 多路複用:

  1. 非阻塞 I/O 水平觸發:
    • select: fd 數量有限制,輪詢檢查 fd。O(n)
    • poll: 無 fd 限制,輪詢檢查fd。O(n)
  2. 非阻塞 I/O邊緣觸發:
    • epoll: 內核紅黑樹管理 fd,事件驅動
  3. 異步 I/O:異步通知,通過信號或者回調

工作模型:

  • 主進程 + 多個 workder 子進程:nginx
    • 主 bind + listen 初始化 socket
    • 子 accept + epoll_wait 都綁定這個 socket
    • 有驚羣問題,需要鎖機制來確保只有一個 worker 節點喚醒
  • 多進程監聽同個端口,需要開啓端口重用,等於是內核將該端口的請求分發到不同的 worker 進程上

高性能網絡模型:

  • DPDK:跳過內核網絡協議棧,直接用戶態輪詢
  • XDP:在內核網絡協議棧前處理網絡包

0x03 網絡優化方式

網絡也是分層的,不同的層有不同的優化手段

  1. 應用層:
    • 優化 I/O 模型
    • 長連接
    • DNS 緩存
  2. socket: 調整內核參數
  3. 傳輸層: 優化傳輸層協議
  4. 網絡層:路由等
  5. 鏈路層:收發包

基本上就是:

  1. 先查看一波網絡性能指標: sar,ip,ss 等工具
  2. tcpdump,wireshark抓包,分析異常網絡流量情況
  3. 調整對應內核參數,基本上可以解決 80% 的問題

0x04 總結

雖然我是計算機網絡專業畢業,但是想一篇文章寫完所有的優化點還是太難了,畢竟計算機網絡是一門單獨的學科,只能把簡單地把網絡原理和優化思路記錄下,在實際使用的時候還是要根據具體的情況來排查問題,另外有很多細節我比較熟悉,覺得太簡單了就不一一記錄了。

相關文章