系统那个网站免费,柳城企业网站建设价格,网站建设大体包含,平台推广营销Nginx学习#xff1a;HTTP核心模块#xff08;八#xff09;文件处理 继续我们的 HTTP 核心模块之旅。今天主要是文件相关的一些处理操作#xff0c;包括 DirectIO、文件缓存以及 sendfile 相关的配置。这三个配置中#xff0c;大家应该会见过 sendfile #xff0c;但是另… 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 maxN [inactivetime]; 默认是 off 也就是关闭状态的。可配置的值包括 maxN设置缓存中元素的最大数量当缓存溢出时使用 LRU(最近最少使用) 算法删除缓存中的元素inactivetime在这段时间内缓存元素如果没有被访问将从缓存中删除。默认超时是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 就会出现下面的内容。 [rootlocalhost html]# strace -p 2365
strace: Process 2365 attached
epoll_wait(15, [{EPOLLIN, {u322915635216, u64140495590854672}}], 512, -1) 1
accept4(8, {sa_familyAF_INET, sin_porthtons(54245), sin_addrinet_addr(192.168.56.1)}, [112-16], SOCK_NONBLOCK) 5
epoll_ctl(15, EPOLL_CTL_ADD, 5, {EPOLLIN|EPOLLRDHUP|EPOLLET, {u322915635912, u64140495590855368}}) 0
epoll_wait(15, [{EPOLLIN, {u322915635912, u64140495590855368}}], 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_modeS_IFDIR|0755, st_size24, ...}) 0
close(6) 0
// 注意这里
writev(5, [{iov_baseHTTP/1.1 301 Moved Permanently\r\n..., iov_len200}, {iov_basehtml\r\nheadtitle301 Moved P..., iov_len116}, {iov_basehrcenternginx/1.23.0/center..., iov_len53}], 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, {u322915635912, u64140495590855368}}], 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_modeS_IFREG|0644, st_size10, ...}) 0
// 注意这里
openat(AT_FDCWD, /usr/local/nginx/html/aaa/index.html, O_RDONLY|O_NONBLOCK) 6
fstat(6, {st_modeS_IFREG|0644, st_size10, ...}) 0
// 注意这里
writev(5, [{iov_baseHTTP/1.1 200 OK\r\nServer: nginx/1..., iov_len235}], 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 max1000 inactive20s;open_file_cache_valid 30s;open_file_cache_min_uses 2;open_file_cache_errors on;...
} 然后再次访问第一次还是会正常出现 openat、fstat 和 close 这三个系统函数的调用。但是之后再次访问就会发现这三个系统调用不见了。 [rootlocalhost html]# strace -p 2423
strace: Process 2423 attached
epoll_wait(15, [{EPOLLIN, {u322915635216, u64140495590854672}}], 512, -1) 1
accept4(8, {sa_familyAF_INET, sin_porthtons(65255), sin_addrinet_addr(192.168.56.1)}, [112-16], SOCK_NONBLOCK) 7
epoll_ctl(15, EPOLL_CTL_ADD, 7, {EPOLLIN|EPOLLRDHUP|EPOLLET, {u322915635912, u64140495590855368}}) 0
epoll_wait(15, [{EPOLLIN, {u322915635912, u64140495590855368}}], 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_modeS_IFDIR|0755, st_size24, ...}) 0
close(12) 0
// 注意这里
writev(7, [{iov_baseHTTP/1.1 301 Moved Permanently\r\n..., iov_len200}, {iov_basehtml\r\nheadtitle301 Moved P..., iov_len116}, {iov_basehrcenternginx/1.23.0/center..., iov_len53}], 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, {u322915635912, u64140495590855368}}], 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_modeS_IFREG|0644, st_size10, ...}) 0
// 注意这里
writev(7, [{iov_baseHTTP/1.1 200 OK\r\nServer: nginx/1..., iov_len235}], 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, {u322915635912, u64140495590855368}}], 512, 65000) 1
recvfrom(7, GET /aaa HTTP/1.1\r\nTEST_UNDERLIN..., 1024, 0, NULL, NULL) 224
writev(7, [{iov_baseHTTP/1.1 301 Moved Permanently\r\n..., iov_len200}, {iov_basehtml\r\nheadtitle301 Moved P..., iov_len116}, {iov_basehrcenternginx/1.23.0/center..., iov_len53}], 3) 369
write(5, 192.168.56.1 - - [07/Aug/2022:23..., 102) 102
epoll_wait(15, [{EPOLLIN, {u322915635912, u64140495590855368}}], 512, 65000) 1
recvfrom(7, GET /aaa/ HTTP/1.1\r\nTEST_UNDERLI..., 1024, 0, NULL, NULL) 260
writev(7, [{iov_baseHTTP/1.1 200 OK\r\nServer: nginx/1..., iov_len235}], 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