[Nginx] 配置中的sendfile參數詳解:從傳統 IO 到零拷貝的性能優化

一、sendfile 是什么?

在這里插入圖片描述

sendfile 是 Nginx 中一個關鍵的配置參數,用于控制是否使用操作系統提供的 sendfile() 系統調用來傳輸文件。

  • sendfile on;:啟用零拷貝技術,直接由內核將文件發送到網絡。
  • sendfile off;:使用傳統方式,數據需經過用戶空間處理。

二、傳統文件傳輸的痛點:為什么要傳到用戶空間?

1. 傳統流程有多麻煩?

以下載一個圖片為例:

  1. read() 系統調用
    • 文件從磁盤通過 DMA(直接內存訪問)拷貝到內核緩沖區。
  2. 用戶空間拷貝
    • 數據從內核緩沖區復制到用戶空間的程序緩沖區。
  3. write() 系統調用
    • 數據從用戶空間寫入網絡套接字緩沖區。
  4. 網絡發送
    • 數據通過 DMA 發送到網卡。

問題總結

  • 兩次內存拷貝(內核 → 用戶空間,用戶空間 → 網絡緩沖區)。
  • 兩次上下文切換(用戶態 ? 內核態)。
  • CPU 資源浪費:頻繁的拷貝和切換消耗大量 CPU 時間。

2. 為什么不能直接從內核發?

早期操作系統的設計限制導致必須將數據傳到用戶空間:

  • 靈活性需求
    • 如果需要對文件內容進行動態處理(如加密、壓縮、添加水印),必須在用戶空間操作。
  • 系統隔離性
    • 用戶空間與內核空間是操作系統的核心設計原則,用戶程序無法直接訪問內核緩沖區。
  • 硬件兼容性
    • 早期網卡只能從用戶空間的緩沖區讀取數據,無法直接從內核緩沖區發送。

三、零拷貝(Zero Copy)的革命:sendfile 的優化

1. 什么是零拷貝?

“零拷貝”并非真正“零”拷貝,而是通過減少內存拷貝次數來優化性能。

  • 傳統方式:2 次內存拷貝(DMA 從磁盤 → 內核緩沖區,內核 → 用戶空間)
  • 零拷貝:1 次內存拷貝(DMA 從磁盤 → 內核緩沖區

2. sendfile 的工作原理

sendfile() 系統調用直接在內核中完成數據傳輸:

  1. DMA 從磁盤 → 內核緩沖區
  2. 內核緩沖區 → 網絡套接字緩沖區
  3. DMA 從網絡緩沖區 → 網卡

關鍵優化

  • 減少一次用戶空間拷貝,節省 CPU 資源。
  • 減少一次上下文切換,提升系統吞吐量。

3. Linux 2.4 的進一步優化:SG-DMA

在 Linux 2.4 內核版本中,引入了 SG-DMA(分散/聚集 DMA) 技術,進一步優化 sendfile 的性能:

  1. DMA 直接從內核緩沖區 → 網卡
  2. 完全省去 CPU 拷貝,實現真正的“零拷貝”。

條件限制

  • 需要網卡支持 SG-DMA(可通過 ethtool -k eth0 | grep scatter-gather 檢查)。

四、為什么大文件又要關閉 sendfile?**

雖然 sendfile 很快,但在某些場景下反而會帶來問題,尤其是大文件下載

原因如下:

  1. 一次性加載整個文件到內存

    • sendfile 默認會把整個文件映射進內存,如果文件很大(如幾個 GB),會導致內存占用飆升。
  2. 影響其他請求響應

    • 如果服務器同時處理多個大文件請求,容易造成內存瓶頸,拖慢整個系統。
  3. 缺乏異步支持

    • 使用 sendfile 時是同步傳輸,不支持異步 I/O,不利于并發處理。

五、sendfile 的性能優化建議

1. 靜態資源優化

http {sendfile        on;tcp_nopush      on;  # 合并數據包,減少網絡碎片tcp_nodelay     off; # 與 tcp_nopush 配合使用
}

2. 大文件下載優化

  • 關閉 sendfile
    location /download {sendfile        off;
    }
    
  • 啟用異步 I/O(aio)
    location /download {aio             on;directio        512k;  # 大于該閾值時使用直接 I/O
    }
    

3. 硬件層面的優化

  • 確保網卡支持 SG-DMA
    ethtool -k eth0 | grep scatter-gather
    
  • 調整內核參數
    • 增大 net.core.wmem_defaultnet.core.rmem_default

七、總結

場景是否開啟 sendfile推薦配置
靜態資源服務? 開啟sendfile on; + tcp_nopush
大文件下載? 關閉sendfile off; + aio + directio
動態生成內容(如 API)? 關閉傳統 read/write 方式

八、常見問題解答

Q1:為什么傳統方式需要傳到用戶空間?

A:早期系統設計需要用戶空間處理動態內容(如加密、壓縮),且網卡硬件不支持直接從內核讀取數據。

Q2:sendfile 一定能提升性能嗎?

A:不一定!需確保網卡支持 SG-DMA,否則僅減少一次拷貝,效果有限。

Q3:如何判斷網卡是否支持 SG-DMA?

A:執行命令 ethtool -k eth0 | grep scatter-gather,輸出為 scatter-gather: on 表示支持。
在這里插入圖片描述

參考: https://dunwu.github.io/nginx-tutorial/#/

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/88016.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/88016.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/88016.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

(LeetCode 每日一題) 2138. 將字符串拆分為若干長度為 k 的組 (字符串、模擬)

題目&#xff1a;2138. 將字符串拆分為若干長度為 k 的組 思路&#xff1a;字符串模擬&#xff0c;時間復雜度0(n)。 C版本&#xff1a; class Solution { public:vector<string> divideString(string s, int k, char fill) {vector<string> v;int ns.size();for…

C++法則1:在 C++ 中,所有的具名變量都是左值,即使它們的類型是右值引用。

看下面例子&#xff1a; test(0)調用的是函數是&#xff1a; template<typename T> void test(T&& t) {std::cout << "右值引用" << std::endl; }test(n)調用的是函數是&#xff1a; template<typename T> void test(T& t) {st…

python如何使用正則提取文章所有形容詞

在Python中使用正則表達式提取文章中的形容詞需要結合語言特性處理。以下是分步解決方案&#xff1a; 英文場景解決方案&#xff08;推薦使用專業NLP庫&#xff09;&#xff1a; import re import nltk nltk.download(averaged_perceptron_tagger) # 首次使用需要下載text …

低代碼平臺的數據歸集及治理

低代碼平臺或無碼平臺&#xff0c;在建表單的時候&#xff0c;都是每一個表單一個json的格式文件&#xff0c;存儲在Nosql數據庫中。在開發的過程中&#xff0c;有以下主要的需求 1、json格式實時的轉為關系數據庫的格式&#xff0c;存入到關系數據庫中 需要在流程結束的時候&…

Origin:如何使柱狀圖看起來懸空

想得到這樣的一個沒有下軸的柱狀圖&#xff0c;操作步驟如下: 1.點擊下軸坐標軸 2.修改效果

Vite 原理深入剖析

1. 整體架構設計 Vite 的整體架構由幾個關鍵模塊組成,每個模塊都對應具體的源碼文件: 開發服務器:用于處理瀏覽器請求、模塊解析和熱更新。開發服務器的代碼主要位于 src/node/server/index.ts。 模塊解析與熱更新:通過模塊中間件攔截請求,處理代碼轉換與熱模塊替換。相關…

微處理器原理與應用篇---常見基礎知識(5)

一、什么是嵌入式系統 嵌入式系統是一種以應用為中心、以計算機技術為基礎、軟硬件可裁剪的專用計算機系統&#xff0c;通常嵌入在其他設備中&#xff0c;用于實現特定功能。它廣泛存在于消費電子、工業控制、汽車電子、醫療設備等領域&#xff0c;是現代智能設備的核心 “大腦…

Redis 8.0向量庫 vs 傳統向量數據庫:大模型知識庫開發選型全指南

在大模型知識庫開發領域&#xff0c;向量數據庫的選擇直接影響系統的性能、擴展性和開發效率。隨著Redis 8.0推出Vector Set數據結構并增強向量搜索能力&#xff0c;開發者面臨新的選擇困境&#xff1a;是采用傳統專用向量數據庫&#xff08;如Milvus、Pinecone&#xff09;&am…

偏向鎖撤銷為什么會觸發STW?

偏向鎖撤銷觸發STW&#xff08;Stop-The-World&#xff09;的根本原因在于其撤銷操作需要??全局內存一致性??和??線程狀態確定性??&#xff0c;具體機制如下&#xff1a; ?? ??一、偏向鎖撤銷的核心流程?? ??競爭觸發撤銷?? 當線程B嘗試獲取已被線程A偏向的…

Java觀察者模式詳解

觀察者模式(Observer Pattern)是一種行為型設計模式&#xff0c;它定義了對象之間的一對多依賴關系&#xff0c;當一個對象(主題)的狀態發生改變時&#xff0c;所有依賴于它的對象(觀察者)都會自動收到通知并更新。 核心概念 觀察者模式包含以下核心角色&#xff1a; ?Subje…

創世新布控球 國標

目錄 結論&#xff1a; UDP模式 對講 平臺頁面設置 設備tcp被動 舊的創世版本&#xff08;平臺選的設備tcp被動&#xff1b;設備側無法設置&#xff09; 新創世從2.8改到180上&#xff0c;先UDP&#xff0c;全報文 參考文檔 結論&#xff1a; 對講的tcp主被動&#xff0…

【Dify精講】第18章:企業級功能定制

在企業級AI應用的實際部署中&#xff0c;你很快就會發現開源版本的標準功能往往無法滿足復雜的業務需求。作為一個在多家企業實施AI系統的老兵&#xff0c;我深知企業級定制的痛點和需求。今天&#xff0c;讓我們一起深入Dify的企業級功能定制&#xff0c;看看如何在現有架構基…

PHP $_GET 變量詳解

PHP $_GET 變量詳解 引言 在PHP編程中,$_GET變量是處理HTTP GET請求參數的一種非常便捷的方式。本文將詳細介紹PHP $_GET變量的使用方法、特點以及在實際開發中的應用。 一、什么是$_GET變量? $_GET是一個預定義的PHP超級全局變量,用于存儲HTTP GET請求中的數據。當用戶…

Kafka動態配置深度解析

在分布式消息隊列領域&#xff0c;Kafka憑借其高吞吐量、低延遲和可擴展性成為眾多企業的首選。隨著業務場景的日益復雜和數據流量的動態變化&#xff0c;靜態配置已難以滿足需求&#xff0c;Kafka的動態配置功能應運而生。通過動態配置&#xff0c;用戶無需重啟集群或中斷服務…

為WIN10微軟輸入法的全角切換Bug禁用Shift+Space組合鍵

20250621 By wdhuag 目錄 前言&#xff1a; 參考&#xff1a; 使用AutoHotkey屏蔽快捷鍵&#xff08;推薦&#xff09;&#xff1a; 使用PowerToys的鍵盤管理器屏蔽快捷鍵&#xff08;不推薦&#xff09;&#xff1a; 網上其它的方法&#xff1a; 前言&#xff1a; 是的…

Shell腳本調試與錯誤處理詳解

在 Shell 腳本中&#xff0c;set 命令用于控制腳本的執行行為和調試選項。以下是詳細解釋&#xff1a; 1. set -e 和 set e set -e&#xff08;嚴格錯誤檢查&#xff09;&#xff1a; 當命令返回非零退出狀態&#xff08;失敗&#xff09;時&#xff0c;立即退出腳本。 示例&a…

鯤鵬服務器創建Zookeeper鏡像實例

配置Kafka過程中&#xff0c;少不了要使用Zookeeer&#xff0c;這里記錄一下配置Zookeeper鏡像實例的過程。 創建目錄 mkdir -p /data/docker/zookeeper/data mkdir -p /data/docker/zookeeper/conf mkdir -p /data/docker/zookeeper/logs說明&#xff1a;data目錄為數據掛載…

GitHub Actions 自動 CI 測試 WorkFlow工作流搭建

大家好&#xff0c;我是此林。 代碼托管平臺 Github 我們應該比較熟悉。每次我們提交代碼到 GitHub 倉庫時&#xff0c;特別是開源項目&#xff0c;一般都會自動觸發測試腳本運行&#xff0c;幫你驗證代碼沒有引入新的錯誤。 這個其實就是 GitHub Actions&#xff0c;一般我們…

0-機器學習簡介

有監督學習 目標&#xff1a;建立一個模型(函數)&#xff0c;來描述輸入(x)和輸出(y)之間的映射關系。 價值&#xff1a;模型訓練完成后&#xff0c;新的輸入&#xff0c;模型會給出預測值輸出。 注意點&#xff1a; 1.要有足夠的訓練樣本 2.輸入和輸出之間有關聯關系 3.輸入…

前端跨域解決方案(6):Nginx

1 Nginx 核心 Nginx 是一個開源的高性能 HTTP 和反向代理服務器&#xff0c;以輕量級、高并發處理能力和低資源消耗著稱。除作為 Web 服務器外&#xff0c;還可充當郵件代理服務器和通用的 TCP/UDP 代理服務器&#xff0c;廣泛應用于現代 Web 架構中。 在 Windows 系統中使用…