标题:【Nginx21】Nginx学习:FastCGI模块(三)缓冲区与响应头

文章目录
    分类:存储运维 标签:Nginx

    Nginx学习:FastCGI模块(三)缓冲区与响应头

    缓存相关的内容占了 FastCGI 模块将近一小半的内容,当然,用过的人可能不多。而今天的内容说实话,我平常也没怎么用过。第一个是缓冲区相关的知识,其实和我们之前学习过的 client_body_buffer_size 有点类似,但它是针对后端动态程序的响应缓冲区来说的。另一个也是响应有关的,主要是响应头相关的一些配置。


    今天学习的内容都是可以设置在 http、server、location 中的,有特殊情况的我会单独说。

    FastCGI缓冲区配置

    就像开头所说的,它和 client_body_buffer_size 的概念是类似的,只不过针对的是后端程序的响应缓冲。什么意思呢?其实就是将响应保存在内存中,如果内容太多,就会保存到一个临时文件里。

    fastcgi_buffering

    启用或禁用来自 FastCGI 服务器的响应缓冲。

    fastcgi_buffering on | off;

    启用缓冲后,Nginx 会尽快收到来自 FastCGI 服务器的响应,并将其保存到由 fastcgi_buffer_size 和 fastcgi_buffers 指令设置的缓冲区中。如果整个响应不适合内存,可以将其中的一部分保存到磁盘上的临时文件中。写入临时文件由 fastcgi_max_temp_file_size 和 fastcgi_temp_file_write_size 指令控制。


    当缓冲被禁用时,响应会在收到时立即同步传递给客户端。 Nginx 不会尝试从 FastCGI 服务器读取整个响应。 Nginx 一次可以从服务器接收的最大数据大小由 fastcgi_buffer_size 指令设置。


    也可以通过在“X-Accel-Buffering”响应头字段中传递“yes”或“no”来启用或禁用缓冲。可以使用 fastcgi_ignore_headers 指令禁用此功能。


    它的默认值就是开启的,用于控制整个 FastCGI 的缓冲区控制,上面已经说明了关闭会发生什么情况。提到的配置指令我们马上一一学习,最后再将所有配置指令合在一起进行一个简单的测试。

    fastcgi_buffer_size

    设置用于读取从 FastCGI 服务器接收到的响应的第一部分的缓冲区大小。

    fastcgi_buffer_size size;

    这部分通常包含一个小的响应头。默认情况下,缓冲区大小等于一个内存页,这是 4K 或 8K,具体取决于平台。然而,它可以做得更小。它和 client_header_buffer_size 这类的配置指令是类似的,就相当于是 FastCGI 版本的。

    fastcgi_buffers

    为单个连接设置用于从 FastCGI 服务器读取响应的缓冲区的数量和大小。

    fastcgi_buffers 8 4k|8k;

    默认情况下,缓冲区大小等于一内存页。这是 4K 或 8K,具体取决于平台。这个配置项是创建几个缓冲区用的,比如设置成 8 4k ,表示的就是 8*4=32k 的缓冲区,而上面的 fastcgi_buffer_size 是第一个头缓冲区的大小,不包含在这边,因此,整个缓冲区的大小就是 8*4k+fastcgi_buffer_size 的结果。它和 client_header_buffer_size 类似,可以看成是主要的响应体的大小。

    fastcgi_busy_buffers_size

    当启用来自 FastCGI 服务器的响应缓冲时,限制在响应尚未完全读取时可能正忙于向客户端发送响应的缓冲区的总大小。

    fastcgi_busy_buffers_size size;

    默认值是 8 或 16 K,其余缓冲区可用于读取响应,并在需要时将部分响应缓冲到临时文件。默认情况下,大小受 fastcgi_buffer_size 和 fastcgi_buffers 指令设置的两个缓冲区的大小限制。

    fastcgi_max_temp_file_size

    该指令设置临时文件的最大大小。

    	fastcgi_max_temp_file_size size;

    默认值是 1024m ,零值表示禁用对临时文件的响应的缓冲。如果启用了来自 FastCGI 服务器的响应缓冲,并且整个响应不适合由 fastcgi_buffer_size 和 fastcgi_buffers 指令设置的缓冲区,则可以将部分响应保存到临时文件中。一次写入临时文件的数据大小由 fastcgi_temp_file_write_size 指令设置。此限制不适用于将缓存或存储在磁盘上的响应。

    fastcgi_temp_file_write_size

    当启用从 FastCGI 服务器到临时文件的响应缓冲时,限制一次写入临时文件的数据大小。

    fastcgi_temp_file_write_size size;

    默认情况下,大小受 fastcgi_buffer_size 和 fastcgi_buffers 指令设置的两个缓冲区限制。临时文件的最大大小由 fastcgi_max_temp_file_size 指令设置。

    fastcgi_temp_path

    定义一个目录,用于存储带有从 FastCGI 服务器接收到的数据的临时文件。

    fastcgi_temp_path path [level1 [level2 [level3]]];

    默认值是 Nginx 运行目录下的 fasstcgi_temp 目录,整体和之前学过的 client_body_temp_path 是类似的,在指定目录下最多可以使用三级子目录层次结构。例如,在以下配置中:

    fastcgi_temp_path /spool/nginx/fastcgi_temp 1 2;

    临时文件可能存储的目录就是:

    /spool/nginx/fastcgi_temp/7/45/00000123457

    前面我们学习的 FastCGI 缓存相关的配置中,缓存临时文件配置项 fastcgi_cache_path 有个参数 use_temp_path 和这个配置项有关系,之前我们已经学习过了。

    综合测试

    新建一个配置,注意要用非正则针对指定目录的配置,要不然会被我们最开始的那个 location ~ \.php 给抢走,因为它那边指定了 php 结尾,优先级比直接指定目录要高,只需要加上 ^~ 就好了,之前在 location 中已经详细讲解过了。

    location ^~ /fastcgi1/ {
      root html;
      fastcgi_pass unix:/var/sock/php-fpm/www.sock;
      fastcgi_index  index.php;
      fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
      include        fastcgi_params;
    
      fastcgi_buffer_size 100;
      fastcgi_buffers 2 100;
      fastcgi_busy_buffers_size 100;
      fastcgi_temp_file_write_size 100;
      fastcgi_temp_path /root/fastcgi_temp_test 1 2;
    }

    都设置得很小是吧,但是我们要准备的 PHP 文件需要返回的响应还是要设置的很大,否则很难看出效果。

    // 1.php
    <?php
    $c = $_GET['c'] ?? 2000;
    for ($i=$c;$i>0;$i--){
    	print_r($_SERVER);
    }

    照理说,我们设置的都只是 100 字节,但实际循环 2000 次返回的响应有 2M 了,这时才能看到指定的 fastcgi_temp_path 文件夹产生了变动,里面也会生成子目录。这一块确实不太理解,设置成 1600 次循环,达不到 2M 的响应,就不会产生临时文件。去掉 fastcgi_temp_file_write_size 的配置之后,2M 的响应也不会产生文件。


    这一块比较难测,而且出来的效果说实话和我们想像的也不太一样。所以如果有大佬知道这是什么情况,欢迎评论留言哈。将来如果有学习或者接触到类似的问题,也会再单独写文章说说。


    另外,上面的数值大家可以乱调一下试试,这几个配置之间有各种限制,比如:

    nginx: [emerg] "fastcgi_temp_file_write_size" must be equal to or greater than the maximum of the value of "fastcgi_buffer_size" and one of the "fastcgi_buffers" in /etc/nginx/nginx.conf:396
    
    
    nginx: [emerg] "fastcgi_busy_buffers_size" must be less than the size of all "fastcgi_buffers" minus one buffer in /etc/nginx/nginx.conf:396

    这些看英文也都能猜到是啥意思了。即使通过检查了,并且 reload 成功之后,请求时也可能会报这些错。

    2022/08/22 22:24:52 [crit] 1811#0: *79 open() "/root/fastcgi_temp_test/0000000001" failed (13: Permission denied) while reading upstream, client: 192.168.56.1, server: core.nginx.test, request: "GET /fastcgi1/1.php HTTP/1.1", upstream: "fastcgi://unix:/var/sock/php-fpm/www.sock:", host: "192.168.56.88"
    
    2022/08/22 22:20:33 [error] 1792#0: *71 upstream sent too big header while reading response header from upstream, client: 192.168.56.1, server: core.nginx.test, request: "GET /fastcgi1/1.php HTTP/1.1", upstream: "fastcgi://unix:/var/sock/php-fpm/www.sock:", host: "192.168.56.88"

    第一个错误是指定的临时文件夹,它的上级目录的权限必须是 755 ,所有 Nginx 下面的文件夹目录都有这个要求。第二个是 fastcgi_buffer_size 设置小了,我想极限测试,也就是设置成 1 ,结果就直接报错了。这个和响应返回的头的大小有关,我这里测试是设置到 76 就可以了,不过为了统一,我就全部设置到 100 了。

    响应头处理

    在 FastCGI 的处理中,HTTP 请求标头字段作为参数传递给 FastCGI 服务器。在作为 FastCGI 服务器运行的应用程序和脚本中,这些参数通常作为环境变量提供。例如,“User-Agent”标头字段作为 HTTP_USER_AGENT 参数传递。除了 HTTP 请求头字段之外,还可以使用 fastcgi_param 指令传递任意参数。这些参数在 PHP 中都可以在 $_SERVER 里面看到。


    对于这些响应头,Nginx 中也有一些字段进行处理,这里不仅是响应头,请求头部分的内容也一起写在这里了。

    fastcgi_hide_header

    默认情况下,nginx 不会从 FastCGI 服务器的响应中将头字段“Status”和“X-Accel-...”传递给客户端。

    fastcgi_hide_header field;

    没有默认值,也就是除了上面那些响应头以外,其它响应头都会进行传递,相反,如果需要允许传递字段,则可以使用 fastcgi_pass_header 指令。


    我们在 PHP 文件中定义一个响应头 header("oopp:111"); ,然后正常查看页面,这个 oopp 会返回来,而添加了 fastcgi_hide_header oopp; 之后,在浏览器上就看不到这个响应头的信息了。

    fastcgi_pass_header

    允许将其他禁用的标头字段从 FastCGI 服务器传递到客户端。

    fastcgi_pass_header field;

    可以指定在禁用列表中的响应头返回,比如 “X-Accel-...” 这些的。具体有哪些可以看后面的 fastcgi_ignore_headers 配置。


    比如我们之前测试过的 X-Accel-Expires 响应头,在 PHP 中设置了,但是前端浏览器的响应头中不会显示,就可以用这个传递到前端浏览器上。


    那么如果 fastcgi_hide_header 和 fastcgi_pass_header 同时设置一个响应头字段呢?以先后顺序为准,后设置的生效。

    fastcgi_ignore_headers

    忽略对来自 FastCGI 服务器的某些响应头字段的处理。

    fastcgi_ignore_headers field ...;

    以下字段可以忽略:“X-Accel-Redirect”、“X-Accel-Expires”、“X-Accel-Limit-Rate”(1.1.6)、“X-Accel-Buffering”(1.1.6) 、“X-Accel-Charset”(1.1.6)、“Expires”、“Cache-Control”、“Set-Cookie”(0.8.44)和“Vary”(1.7.7)。


    如果未禁用,则处理这些标头字段具有以下效果:

    • “X-Accel-Expires”、“Expires”、“Cache-Control”、“Set-Cookie”、“Vary”设置响应缓存的参数

    • “X-Accel-Redirect”执行到指定 URI 的内部重定向

    • “X-Accel-Limit-Rate”设置向客户端传输响应的速率限制

    • “X-Accel-Buffering”启用或禁用响应缓冲

    • “X-Accel-Charset”设置响应的所需字符集

    默认值是空的,就是这些都会处理,假如设置一个 X-Accel-Expires ,那么我们之前在 PHP 中设置的 X-Accel-Expires 响应头延长缓存时间的效果就不起作用了。

    总结

    缓冲区部分可能还是需要更深入的学习操作系统及网络相关的知识才能够解释清楚,目前我的水平也就只能到这里了。测试代码也是按自己的想法来进行测试的。另外一块的响应头部分比较简单,大家可以自己测试一下哦。


    参考文档:


    http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html

    视频链接

    微信文章地址:https://mp.weixin.qq.com/s/tlznLZKjulf1U7NOYL-tXA

    B站视频地址:https://www.bilibili.com/video/BV16a4y1D7QP

    搜索
    关注