【Nginx11】Nginx学习:HTTP核心模块(八)文件处理

这篇具有很好参考价值的文章主要介绍了【Nginx11】Nginx学习:HTTP核心模块(八)文件处理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Nginx学习:HTTP核心模块(八)文件处理

继续我们的 HTTP 核心模块之旅。今天主要是文件相关的一些处理操作,包括 DirectIO、文件缓存以及 sendfile 相关的配置。这三个配置中,大家应该会见过 sendfile ,但是另外两个就比较少见了。包括我之前也从来没见过,不过还好,DirectIO 并不是一个完全的陌生人,文件缓存优化也与操作系统基础知识有关,而 sendfile 一般默认就是开启的,所以大家也不要有太大的压力哦。

directio

是不是看着很眼熟,没错,早前我们在 PHP 的小课堂文章中学习过。没印象或者想不起来的小伙伴可以移步 PHP中DirectIO直操作文件扩展的使用https://mp.weixin.qq.com/s/fS6X2IlrnrBrBZwwqRF3vA (去博客搜索也可以哦) 去回忆一下哦。别的不多说了,直接来看看相关的配置。由于不知道要怎么测试,所以就简单地介绍一些这些配置就好了,如果有小伙伴了解这一块要怎么测试的,可以评论区留言哦。

directio

当读入长度大于等于指定 size 的文件时,开启 DirectIO 功能。

directio size | off;

具体的做法是, 在 FreeBSD 或 Linux 系统开启使用 O_DIRECT 标志, 在 Mac OS X 系统开启使用 F_NOCACHE 标志, 在 Solaris 系统开启使用 directio() 功能。这条指令自动关闭 sendfile(0.7.15版) 。它在处理大文件时 directio 4m; 或者在 Linux 系统使用 aio 时比较有用。默认 off 。

directio_alignment

为 DirectIO 设置文件偏移量对齐。

directio_alignment size;

大多数情况下,按512字节对齐足矣, 但在 Linux 系统下使用 XFS ,需要将值扩大到 4K 。

文件优化缓存

这个缓存是个什么东西呢?它可以用于减少 Nginx 的系统调用,缓存文件句柄、大小和修改时间等。具体作用我们在最后会看到。

open_file_cache

用于配置文件缓存。

open_file_cache off;
open_file_cache max=N [inactive=time];

默认是 off ,也就是关闭状态的。可配置的值包括:

  • max=N,设置缓存中元素的最大数量,当缓存溢出时,使用 LRU(最近最少使用) 算法删除缓存中的元素

  • inactive=time,在这段时间内缓存元素如果没有被访问,将从缓存中删除。默认超时是60秒

它可以缓存的内容包括:

  • 打开文件的描述符,大小和修改时间

  • 目录查找结果

  • 文件查找时的错误结果,诸如“file not found”(文件不存在)、“no read permission”(无读权限) 等等

在使用文件缓存的时候,最好 open_file_cache_errors 也开启,这个命令我们后面马上会说。

open_file_cache_errors

开启或者关闭缓存文件查找的错误结果

open_file_cache_errors on | off;

默认值是 off ,如果确定要使用文件缓存的话,最好把它也打开。

open_file_cache_min_uses

设置在由 open_file_cache 指令的 inactive 参数配置的超时时间内, 文件应该被访问的最小 number(次数) 。

open_file_cache_min_uses number;

如果访问次数大于等于此值,文件描述符会保留在缓存中,否则从缓存中删除。

open_file_cache_valid

设置检查 open_file_cache 缓存的元素的时间间隔。

open_file_cache_valid time;

默认 60s 检查一次。

配置测试

首先使用 strace 命令追踪一下当前 Nginx 的 Worker 进程,为了方便测试,咱们可以把 worker_processes 设置为 1 ,只启动一个工作进程。然后随便请求一个 URL 就会出现下面的内容。

[root@localhost html]# strace -p 2365
strace: Process 2365 attached
epoll_wait(15, [{EPOLLIN, {u32=2915635216, u64=140495590854672}}], 512, -1) = 1
accept4(8, {sa_family=AF_INET, sin_port=htons(54245), sin_addr=inet_addr("192.168.56.1")}, [112->16], SOCK_NONBLOCK) = 5
epoll_ctl(15, EPOLL_CTL_ADD, 5, {EPOLLIN|EPOLLRDHUP|EPOLLET, {u32=2915635912, u64=140495590855368}}) = 0
epoll_wait(15, [{EPOLLIN, {u32=2915635912, u64=140495590855368}}], 512, 60000) = 1
recvfrom(5, "GET /aaa HTTP/1.1\r\nTEST_UNDERLIN"..., 1024, 0, NULL, NULL) = 224
// =======注意这里=======
openat(AT_FDCWD, "/usr/local/nginx/html/aaa", O_RDONLY|O_NONBLOCK) = 6
fstat(6, {st_mode=S_IFDIR|0755, st_size=24, ...}) = 0
close(6)                                = 0
// =======注意这里=======
writev(5, [{iov_base="HTTP/1.1 301 Moved Permanently\r\n"..., iov_len=200}, {iov_base="<html>\r\n<head><title>301 Moved P"..., iov_len=116}, {iov_base="<hr><center>nginx/1.23.0</center"..., iov_len=53}], 3) = 369
write(7, "192.168.56.1 - - [07/Aug/2022:22"..., 102) = 102
setsockopt(5, SOL_TCP, TCP_NODELAY, [1], 4) = 0
epoll_wait(15, [{EPOLLIN, {u32=2915635912, u64=140495590855368}}], 512, 65000) = 1
recvfrom(5, "GET /aaa/ HTTP/1.1\r\nTEST_UNDERLI"..., 1024, 0, NULL, NULL) = 260
stat("/usr/local/nginx/html/aaa/index.html", {st_mode=S_IFREG|0644, st_size=10, ...}) = 0
// =======注意这里=======
openat(AT_FDCWD, "/usr/local/nginx/html/aaa/index.html", O_RDONLY|O_NONBLOCK) = 6
fstat(6, {st_mode=S_IFREG|0644, st_size=10, ...}) = 0
// =======注意这里=======
writev(5, [{iov_base="HTTP/1.1 200 OK\r\nServer: nginx/1"..., iov_len=235}], 1) = 235
sendfile(5, 6, [0] => [10], 10)         = 10
write(7, "192.168.56.1 - - [07/Aug/2022:22"..., 125) = 125
close(6)                                = 0
epoll_wait(15,

主要需要看的就是上面注释中的部分,有三个操作,分别是 openat、fstat 和 close 操作,分别对应着打开文件句柄、获取文件统计信息以及关闭文件句柄这三个操作。目前的情况下,多次访问,还是一样的结果,每次都会有这三个步骤。

接下来,我们就简单配置下文件缓存,直接使用官方文档中提供的示例配置。这几个命令可以配置在 http、server、location 中,我们就简单地在 server 中进行配置吧。

server {
  ...
  open_file_cache          max=1000 inactive=20s;
  open_file_cache_valid    30s;
  open_file_cache_min_uses 2;
  open_file_cache_errors   on;
  ...
}

然后再次访问,第一次还是会正常出现 openat、fstat 和 close 这三个系统函数的调用。但是之后再次访问,就会发现这三个系统调用不见了。

[root@localhost html]# strace -p 2423
strace: Process 2423 attached
epoll_wait(15, [{EPOLLIN, {u32=2915635216, u64=140495590854672}}], 512, -1) = 1
accept4(8, {sa_family=AF_INET, sin_port=htons(65255), sin_addr=inet_addr("192.168.56.1")}, [112->16], SOCK_NONBLOCK) = 7
epoll_ctl(15, EPOLL_CTL_ADD, 7, {EPOLLIN|EPOLLRDHUP|EPOLLET, {u32=2915635912, u64=140495590855368}}) = 0
epoll_wait(15, [{EPOLLIN, {u32=2915635912, u64=140495590855368}}], 512, 60000) = 1
recvfrom(7, "GET /aaa HTTP/1.1\r\nTEST_UNDERLIN"..., 1024, 0, NULL, NULL) = 224
// =======注意这里=======
openat(AT_FDCWD, "/usr/local/nginx/html/aaa", O_RDONLY|O_NONBLOCK) = 12
fstat(12, {st_mode=S_IFDIR|0755, st_size=24, ...}) = 0
close(12)                               = 0
// =======注意这里=======
writev(7, [{iov_base="HTTP/1.1 301 Moved Permanently\r\n"..., iov_len=200}, {iov_base="<html>\r\n<head><title>301 Moved P"..., iov_len=116}, {iov_base="<hr><center>nginx/1.23.0</center"..., iov_len=53}], 3) = 369
write(5, "192.168.56.1 - - [07/Aug/2022:23"..., 102) = 102
setsockopt(7, SOL_TCP, TCP_NODELAY, [1], 4) = 0
epoll_wait(15, [{EPOLLIN, {u32=2915635912, u64=140495590855368}}], 512, 65000) = 1
recvfrom(7, "GET /aaa/ HTTP/1.1\r\nTEST_UNDERLI"..., 1024, 0, NULL, NULL) = 260
// =======注意这里=======
openat(AT_FDCWD, "/usr/local/nginx/html/aaa/index.html", O_RDONLY|O_NONBLOCK) = 12
fstat(12, {st_mode=S_IFREG|0644, st_size=10, ...}) = 0
// =======注意这里=======
writev(7, [{iov_base="HTTP/1.1 200 OK\r\nServer: nginx/1"..., iov_len=235}], 1) = 235
sendfile(7, 12, [0] => [10], 10)        = 10
write(5, "192.168.56.1 - - [07/Aug/2022:23"..., 125) = 125
// 这里开始是后续访问
epoll_wait(15, [{EPOLLIN, {u32=2915635912, u64=140495590855368}}], 512, 65000) = 1
recvfrom(7, "GET /aaa HTTP/1.1\r\nTEST_UNDERLIN"..., 1024, 0, NULL, NULL) = 224
writev(7, [{iov_base="HTTP/1.1 301 Moved Permanently\r\n"..., iov_len=200}, {iov_base="<html>\r\n<head><title>301 Moved P"..., iov_len=116}, {iov_base="<hr><center>nginx/1.23.0</center"..., iov_len=53}], 3) = 369
write(5, "192.168.56.1 - - [07/Aug/2022:23"..., 102) = 102
epoll_wait(15, [{EPOLLIN, {u32=2915635912, u64=140495590855368}}], 512, 65000) = 1
recvfrom(7, "GET /aaa/ HTTP/1.1\r\nTEST_UNDERLI"..., 1024, 0, NULL, NULL) = 260
writev(7, [{iov_base="HTTP/1.1 200 OK\r\nServer: nginx/1"..., iov_len=235}], 1) = 235
sendfile(7, 12, [0] => [10], 10)        = 10
write(5, "192.168.56.1 - - [07/Aug/2022:23"..., 125) = 125
epoll_wait(15,

很明显,这就是文件缓存在起作用。减少了文件相关的系统调用读取的次数。为什么我们上面访问的内容会有两遍请求呢?我访问的是 /aaa 目录,直接访问目录会找这个目录下面的 index.html 文件,因此有一次 301 跳转。你也可以直接访问 /aaa/index.html 就会看得更清楚一些了。

这一套文件缓存不会缓存文件的具体内容,而只是操作符句柄及文件的一些统计信息,Nginx 虽然已经对静态内容做过优化。但在高流量网站的情况下,仍然可以使用 open_file_cache 进一步提高性能,减少系统调用。通过扩大这个缓存的容量可以提高线上的实际命中率。但是缓存容量并不是越大越好,比如当达到 20000 个元素的容量时,共享内存的锁就成了瓶颈。所以,可以在确定访问频次非常高的静态文件 location 或者 server 上开启这一套文件缓存,数量也不用太多,可以让性能有更进一步的提升。

PHP-FPM 或者反向代理之类的和这个文件缓存就没啥关系了,PHP-FPM 走的是 socket 句柄,通过连接 PHP-FPM 进行操作,而打开 php 文件的是 PHP-FPM ,不是 Nginx 。

sendfile

这一块又要牵涉到操作系统了。在操作系统编程中,sendfile() 是系统调用,而 read() 这种是函数调用,因此,使用 sendfile() 对于文件读取来说会带来性能的提升。

读取发送文件的时候,使用了 sendfile() 那么 Nginx 就会直接向系统内核发送指令,然后发送文件也是系统内核直接完成,只有一次复制操作,实现了异步网络 IO 的形式。而传统情况则是从磁盘中以流的形式加载文件,然后再将文件流复制到系统内核中,内核再发送。区别就在这里。其实就是说,传统方式在读写文件时,会从硬盘到系统空间,再到用户空间这样走一圈,而使用 sendfile() 则只在系统空间,不用走到用户空间,从而实现零拷贝,减少空间切换的消耗。

当然,sendfile 只对静态网站有用,也就是确实需要进行文件读写发送的。如果是动态网站,比如 FastCGI 或反向代理的,对接的实际上是 socket 接口,真正的文件处理是在动态语言中进行的,比如 PHP 的模板文件加载等。因此,它只对静态页面或文件有性能提升的效果。

sendfile

开启或关闭使用 sendfile() 调用。

sendfile on | off;

现在默认就是打开的,从 nginx 0.8.12 和 FreeBSD 5.2.1 开始,可以使用 aio 预加载 sendfile的数据,Linux 没有哦。

send_lowat

如果设置成非 0 值,Nginx 将尝试最小化向客户端发送数据的次数。

send_lowat size;

默认值是 0 ,它是通过将 kqueue 方法的 NOTE_LOWAT 标志, 或者将套接字的 SO_SNDLOWA T属性设置成指定的 size 实现的。这条指令在Linux、Solaris和Windows操作系统无效。

sendfile_max_chunk

设置为非0值时,可以限制在一次 sendfile() 调用时传输的数据量。

sendfile_max_chunk size;

最新的版本默认 2m,如果不进行限制,一个快速的连接可能会霸占整个worker进程的所有资源。在版本1.21.4之前,默认情况下是 0 ,没有限制。

总结

好吧好吧,今天的内容有点水,因为我确实不知道 DirectIO 和 sendfile 在 Nginx 中要怎么测试。如果有了解过的小伙伴记得评论留言哦。不过通常来说,我们会在刚安装好的 Nginx 配置文件中看到 sendfile 是 on 的状态,一般来说,不懂的就别瞎配了,咱惹不起还躲不起嘛,其它的配置让它们就走默认好了。还是那句话,留个印象,将来如果有用到的时候,能够想起来并且查资料能有个方向就够了。毕竟,现在的水平只到这里,谁知道将来我们能不能成为大神呢,要是真成了,再回来好好补上呗!

参考文档:

http://nginx.org/en/docs/http/ngx_http_core_module.html文章来源地址https://www.toymoban.com/news/detail-608769.html

到了这里,关于【Nginx11】Nginx学习:HTTP核心模块(八)文件处理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Nginx06】Nginx学习:HTTP核心模块(三)Location

    Location 是整个 HTTP 模块中非常重要的一个子模块,它是为某个请求URI(路径)建立配置。这个模块又是属于 Server 模块的子模块,同时它还可以嵌套在另一个 Location 模块下面,因此,它的作用范围是 server 和 location 。其实,说白了,也就是我们可以为指定的一些路径去做一些

    2024年02月15日
    浏览(38)
  • 【Nginx15】Nginx学习:HTTP核心模块(十二)内嵌变量

    关于内嵌变量,其实就是 Nginx 开放给我们的在配置文件中可以使用的变量。源码中无非就是替换成真实的代码变量进行操作。这些变量可以帮助我们做很多事情。之前的文章中其实也有不少地方用到了,比如说  $uri  这个变量,是不是已经见过很多次了。而且这些变量基本

    2024年02月14日
    浏览(38)
  • 【Nginx13】Nginx学习:HTTP核心模块(十)Types、AIO及其它配置

    今天学习的内容也比较简单,主要的是 Types 相关的配置,另外还会了解一下 AIO 以及部分没有特别大的分类归属的配置指令的使用。后面的内容都是 HTTP 核心模块中比较小或者比较简单的部分了。有很多配置项其实我们平常并不常用,甚至很多在学习之前我都不知道有它们的

    2024年02月12日
    浏览(46)
  • 【Nginx12】Nginx学习:HTTP核心模块(九)浏览器缓存与try_files

    浏览器缓存在 Nginx 的 HTTP 核心模块中其实只有两个简单的配置,这一块也是 HTTP 的基础知识。之前我们就一直在强调,学习 Nginx 需要的就是各种网络相关的基础知识,其中更重要的就是 HTTP 和 TCP 相关的内容。另外一个 try_files 配置指令也是 Nginx 中非常常用的一个指令,用于

    2024年02月15日
    浏览(36)
  • 万字长文!一次性弄懂 Nginx 处理 HTTP 请求的 11 个阶段

    本文涉及到的所有配置文件我已经放在了 Nginx 配置文件,大家可以自取。 前面给大家讲了 Nginx 是如何处理 HTTP请求头部的,接下来就到了真正处理 HTTP 请求的阶段了。先看下面这张图,这张图是 Nginx 处理 HTTP 请求的示意图,虽然简单,但是却很好的说明了整个过程。 Read

    2024年04月16日
    浏览(47)
  • 【Nginx18】Nginx学习:WebDav文件存储与图片媒体处理模块

    今天的内容怎么说呢?有两个感觉非常有意思,另外一些就差点意思。有意思的是,咱们可以直接用 Nginx 的 Webdav 功能搭建一个网盘,另外也可以实现动态的图片处理。这两个功能吧,有其局限性,但也非常方便。另外的流媒体部分的内容,主要 FLV 和 MP4 这两种视频媒体格式

    2024年02月12日
    浏览(42)
  • nginx http模块

    location的定义包含以下几种 =:表示精确匹配,只有请求的url路径与后面的字符串完全相等时,才会命中,不支持location嵌套 ~:表示使用正则定义的,区分大小写 ~*:表示是使用正则定义的,不区分大小写 ^~:表示该符号后面的字符是最佳匹配,采用该规则,不再进行后续的查

    2023年04月08日
    浏览(35)
  • Nginx安装http2和ssl模块

    Nginx在执行默认安装命令的时候,并不会编译启用ngx_http_v2_module模块。故在修改Nginx配置文件启用http2.0协议的时候会报错。 一.检查Nginx安装了哪些模块 如图就是没有安装ngx_http_v2_module模块 二.重新编译Nginx Nginx有两个目录,一个是安装目录,一个是源码目录,安装目录就是执

    2024年01月16日
    浏览(40)
  • Nginx ngx_http_auth_request_module模块鉴权

    ngx_http_auth_request_module 模块 实现了基于一子请求的结果的客户端的授权。如果子请求返回2xx响应码,则允许访问。如果它返回401或403,则访问被拒绝并显示相应的错误代码。子请求返回的任何其他响应代码都被认为是错误的。 auth_request 使用的也是 subrequest 进行子请求。 当我

    2024年02月17日
    浏览(55)
  • 使用nginx实现自定义大小预览缩略图,http_image_filter模块的安装使用

    本预览图功能使用的是nginx的http_image_filter模块,可以自定义缓存大小解决占用服务器容量问题,建议配合fastDFS使用 http_image_filter不会改变图片原始比例 例如原始图片尺寸为16:9,那么输入宽高值之后会以较小的一个参数展现预览图,比如原始图为1600*900,传递参数320*90会拿到

    2023年04月24日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包