Nignx sendfile 选项原理和实现

1 简介

Linux kernel2.2版本引入了sendfile这种 零拷贝(zero-copy)” 系统调用机制进行文件传输大大提高了静态文件的传输速度。Nginx随后也增加sendfile这一选项用来加速文件传输速度。

本文我们试图去分析sendfile提升文件传输速度的奥秘以及从代码层面分析nginx是如何使用sendfile进行加速的。

2 配置

Nginx的sendfile选项是一个开关值,默认值是关闭。可以通过如下HTTP context定义sendfile 的数值为on或者off用来打开和关闭sendfile功能。

http {

…..

sendfile on;

}

3 原理

简单地说,sendfile提升文件传输的秘密就是减少了数据从内核空间到用户空间的拷贝以及减少了上下文切换次数因而减少了上下文切换带来的系统开销。

如果我们不采用sendfile去传输数据,那么一般文件传输的流程为:

  1. 使用read函数读取文件,发生进程切换,从用户空间切换到内核空间。
  2. 在内核空间文件数据从硬盘被读入了内核缓冲区。(DMA)
  3. 当read函数执行结束后,数据从内核缓冲区被拷贝到用户缓冲区。此时会发生上下文切换,从内核空间切换到用户空间。
  4. 等用户进程再次得到调度时,就可以操作用户缓冲区内的数据了。
  5. 调用write函数发送数据,这时又发生一次上下文切换,丛用户空间切换到内核空间。把用户缓冲区数据再次拷贝到socket缓冲区。
  6. 当write函数执行返回,再一次的上下文切换,从内核空间切换到了用户空间。
  7. 当数据真正被发送时,又被从socket缓冲区拷贝协议栈缓冲区进行发送。

整个流程如下图所示:

                                                        图一 不采用sendfile数据发送流程

采用sendfile传输数据,文件的传输流程为:

  1. 使用sendfile函数,指定要传输的文件和要发送的目标socket 描述符。发生进程切换,从user空间切换到kernel空间。
  2. 在kernel空间文件数据从硬盘被读入内核缓冲区。
  3. 在kernel空间把数据从内核缓冲区拷贝到目标socket缓冲区。
  4. 函数sendfile返回,从kernel空间切换到用户空间。
  5. 当数据真正被发送时,数据从socket缓冲区copy到协议栈缓冲区进行发送。

整个流程如下图所示:

                                                                         图二 采用sendfile数据发送流程

4 实现

配置层面

选项sendfile的配置实现非常简单,作为一个httpcontext的一个flag, 对硬的解析配置函数是ngx_conf_set_flag_slot 。 函数得到执行时会把sendfile参数设置为1。

数据层面

在Nginx自己的IO发送结构ngx_os_io_t中,有一个函数指针成员变量send_chain。此函数用来发送数据。在linux平台上,对应的实现函数是ngx_linux_sendfile_chain。有http模块很多的发送函数中比如ngx_chain_writer ngx_http_write_filter以及ngx_http_v2_send_output_queue都可能会调用send_chain此函数指针。在Linux平台上也就是对应的实现函数ngx_linux_sendfile_chain被调用。在ngx_linux_sendfile_chain函数执行时,如果sendfile的配置为on则ngx_linux_sendfile被调用,如果是off则数据通过ngx_writev进行发送。

五 结语

为了提升性能,大到框架设计,小到细节实现Nginx都做了充分的努力,充分地挖掘系统的能力。本文提到的sendfile也是Nginx众多提升性能的一个办法。随着ebpf以及xdp的兴起,未来不远,或许我们也能看到ebpf和xdp在Nginx中的身影。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值