Linux 性能分析總結之網絡(六)
摘要:中斷程序分配一個叫 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 收包
- 網卡 DMA(可以理解爲直接讀 I/O 到內存,減少 cpu 的介入) 把收到的網絡幀放到收包隊列(在內存中),硬中斷通知中斷程序處理
- 中斷程序分配一個叫 sk_buff 的 socket buffer數據結構,拷貝網絡幀到這個結構,然後軟中斷通知內核來處理網絡幀了
- 內核獲得網絡幀後,就跟剝洋蔥一樣,一層層的剝開
- 數據鏈路層:檢查報文,去掉幀頭幀尾,看 ip 層是什麼報文,如果是 6 就交給上層 ipv6 對應的協議處理,如果是 4 就交給 4
- IP層: 判斷網絡包走向,是轉發還是交給上層處理。比如 iptable 中的 forward 鏈就是轉發鏈,如果要交給上層則確定上層協議是 tcp/udp 等,並去掉頭尾
- 傳輸層:根據 tcp/udp 頭,根據四元組找到對應的 socket,然後把數據拷貝到 socket 裏
- 應用層:操作 socket 讀取數據
0x0102 發包
- 應用層:通過系統調用,把數據包寫到 socket 裏
- 傳輸層:增加 tcp 頭
- ip 層:增加 ip 頭,路由尋址,找到下一跳,根據 MTU 分片
- 數據鏈路層:根據 mac 地址尋址,找到下一跳的 mac,增加頭尾,放到發包隊列,軟中斷通知中斷程序驅動
- 物理層:驅動程序 DMA 讀取網絡幀,通過物理網卡通過脈衝信號或光信號發包
0x0110 性能指標
- 帶寬: 最大傳輸速率
- 吞吐量: 單位時間內傳輸數據量
- 延時: 發出請求到收到響應的時間
- PPS: Packet Per Second,每秒發包量
- 網絡可用性
- 併發數
- 丟包率
- 重傳率
0x02 網絡 I/O 原理
I/O通知方式:
- 水平觸發: 應用程序 可以隨時讀fd
- 邊緣觸發: 只能在 fd 發生變化是纔可以讀
I/O 多路複用:
- 非阻塞 I/O 水平觸發:
- select: fd 數量有限制,輪詢檢查 fd。O(n)
- poll: 無 fd 限制,輪詢檢查fd。O(n)
- 非阻塞 I/O邊緣觸發:
- epoll: 內核紅黑樹管理 fd,事件驅動
- 異步 I/O:異步通知,通過信號或者回調
工作模型:
- 主進程 + 多個 workder 子進程:nginx
- 主 bind + listen 初始化 socket
- 子 accept + epoll_wait 都綁定這個 socket
- 有驚羣問題,需要鎖機制來確保只有一個 worker 節點喚醒
- 多進程監聽同個端口,需要開啓端口重用,等於是內核將該端口的請求分發到不同的 worker 進程上
高性能網絡模型:
- DPDK:跳過內核網絡協議棧,直接用戶態輪詢
- XDP:在內核網絡協議棧前處理網絡包
0x03 網絡優化方式
網絡也是分層的,不同的層有不同的優化手段
- 應用層:
- 優化 I/O 模型
- 長連接
- DNS 緩存
- socket: 調整內核參數
- 傳輸層: 優化傳輸層協議
- 網絡層:路由等
- 鏈路層:收發包
基本上就是:
- 先查看一波網絡性能指標: sar,ip,ss 等工具
- tcpdump,wireshark抓包,分析異常網絡流量情況
- 調整對應內核參數,基本上可以解決 80% 的問題
0x04 總結
雖然我是計算機網絡專業畢業,但是想一篇文章寫完所有的優化點還是太難了,畢竟計算機網絡是一門單獨的學科,只能把簡單地把網絡原理和優化思路記錄下,在實際使用的時候還是要根據具體的情況來排查問題,另外有很多細節我比較熟悉,覺得太簡單了就不一一記錄了。