[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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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 系统中使用…