Nginx sendfile

Nginx sendfile教程

Nginx 中,开启 sendfile 配置来提高文件的传输速率,大多数 sendfile 配置开启后,Nginx 在进行数据传输,会调用 sendfile() 函数。

sendfile 是 Linux 2.0+ 以后的推出的一个系统调用。对比一般的数据的网络传输 sendfile 会有更少的切换和更少的数据拷贝。

Nginx sendfile原理

linux的正常IO

Linux 正常的 IO 如下:

read(file, tmp_buf, len); write(socket, tmp_buf, len);

此种情况下数据的传输经过了两个函数调用实际上经过以下的一些底层步骤:

  1. 系统调用 read 函数产生一次切换,user mode→kernel mode 将数据通过 DMA 拷贝至 kernel buffer。
  2. kernel buffer 利用 DMA 数据拷贝至 user buffer,write 函数返回,此时又产生一次上下文切换,kernel mode→user mode。
  3. 系统调用 write 函数,又产生一次上下文切换 user mode →kernel mode,用 DMA 方式,将数据从 user buffer 拷贝至 kernel socket buffer。
  4. write 函数返回,又产生一次上下文切换,kernel mode →user mode 将数据从 kernel socket buffer 拷贝至协议栈。
  5. 总的来说数据发生了四次拷贝,产生了四次上下文切换。磁盘→kernel buffer→user buffer→kernel socket buffer→存储协议。

调用sendfile函数

sendfile(socket, file, len);

调用 sendfile 函数,经过的过程是这样的:磁盘→kernel buffer→kernel socket buffer→协议栈,产生一次系统调用,两次上下文切换,三次数据拷贝。

步骤减少了,切换减少了,拷贝减少了,自然性能就提升了。

什么是DAM

DMA(Direct Memory Acess)是一种不通过 CPU,直接在系统内存和外设之间交互数据的接口技术。正常来说如果使用 CPU 来进行数据交换,则需要首先使用 CPU 读取外设字节至内部寄存器,然后再将寄存器中的字节写入内存。而 DMA 的出现则可以直接将外设字节一次写入内存,加快了数据写入内存的速度。

sendfile配置

语法

sendfile on | off;

默认

sendfile off;

使用环境

http,server,location,if in location

说明

指定是否使用 sendfile 系统调用来传输文件。sendfile 系统调用在两个文件描述符之间直接传递数据(完全在内核中操作),从而避免了数据在内核缓冲区和用户缓冲区之间的拷贝,操作效率很高,被称之为零拷贝。

Nginx sendfile配置

我们首先,使用 htpasswd 工具,生成一个密码认证的文件,具体命令如下:

htpasswd -c /etc/nginx/auth_conf haicoder

这里的 haicoder 就是认证的用户名,生成完毕后,如下图所示:

33_nginx密码认证.png

现在,我们使用 ls 命令,查看生成文件,执行完毕后,如下图所示:

34_nginx密码认证.png

我们看到,密码认证文件已经存在了,现在,我们使用 vim 打开 nginx 的默认配置路径,具体命令如下:

vim /etc/nginx/conf.d/default.conf

我们执行如上命令,打开配置文件,接着,我们在 server 下面增加一个 location 配置,具体配置如下:

location / { root /opt/app/code; index index.html index.htm; } location ~ ^/haicoder.html { root /opt/app/code; auth_basic "Pls input your password!"; auth_basic_user_file /etc/nginx/auth_conf; index index.html; }

配置完毕后,如下图所示:

35_nginx密码认证.png

现在,我们重新加载配置文件,具体命令如下:

nginx -s reload

现在,我们使用浏览器访问 nginx,浏览器输出如下:

36_nginx密码认证.png

我们看到,我们的配置已经生效了,我们现在的访问,需要我们输入用户名和密码了,现在,我们输入正确的用户名和密码,此时浏览器输出如下:

37_nginx密码认证.png

我们看到,可以正常访问了。

Nginx登录认证总结

在 Nginx 中,http_auth_basic_module 模块实现访问必须输入用户名和密码,在用户名和密码正确的情况下才可以访问,这为我们一些重要资源访问增添了一道安全锁。