深圳正规网站建设公司,wordpress如何设置页面布局,做胎压的网站,类模板模板下载网站Nginx学习#xff1a;HTTP核心模块#xff08;七#xff09;请求体及请求限流 对于一个请求来说#xff0c;请求行、请求头、请求体共同构成了它的整体。不过如果仅仅是 GET 请求的话#xff0c;其实一般会忽略掉请求体。但是#xff0c;现在大部分的伪 RESTful 开发风格… Nginx学习HTTP核心模块七请求体及请求限流 对于一个请求来说请求行、请求头、请求体共同构成了它的整体。不过如果仅仅是 GET 请求的话其实一般会忽略掉请求体。但是现在大部分的伪 RESTful 开发风格基本上已经变成了全部都是 POST 的天下了。特别是小型公司不管前后端分离还是小程序、APP一套 POST 走天下。 这也不怪我们懒或者不规范小公司毕竟是以成本以效率来搏命的即使是我自己弄一些小东西也只是想着怎么简单怎么来不会去考虑那么复杂的实现。也正因此POST 中请求体的部分确实是现在非常重要的内容。下面我们来详细看看相关的配置都有哪些。另外请求限流部分的内容是我之前从来没接触过的虽说也看过一点相关的知识知道一些什么令牌桶之类的名词但确实从没有自己写过。因此请求限流部分也只是简单地测试和演示没法给出更详细的原理及解释。 请求正文 请求正文指的就是发来的请求中body 部分的内容也就是我们常说的 POST 请求的请求体部分。这一部分的配置主要是请求体的大小、超时时间、缓冲区等等。请求正文相关的配置项都可以用于 http、server、location 各个模块中。 client_body_buffer_size 设置读取客户端请求正文的缓冲容量。 client_body_buffer_size size; 如果请求正文大于缓冲容量整个正文或者正文的一部分将写入临时文件。缓冲大小默认等于两块内存页的大小在x86平台、其他 32 位平台和 x86-64 平台这个值是8K。在其他 64 位平台这个值一般是 16K 。 我们和下面的配置一起测试这个配置指令。 client_body_temp_path 定义存储客户端请求正文的临时文件的目录没错就是上面的超出 client_body_buffer_size 设置大小的数据所保存的临时文件的位置。默认情况下它是位于当前运行的 Nginx 程序目录下的 client_body_temp 比如我这里就是在这里 [rootlocalhost nginx]# pwd
/usr/local/nginx
[rootlocalhost nginx]# ll
total 0
drwx------. 2 www root 6 Jul 13 23:35 client_body_temp 它的配置参数是这样的。 client_body_temp_path path [level1 [level2 [level3]]]; 这个 path 写相对路径或者绝对路径都可以如果是相对路径那么它对应的路径就是运行的 Nginx 程序所在的目录和日志那些一样。参数后面的 level1 之类的参数表示的是子目录的结构最多可以支持三层比如下面这样的配置。 client_body_temp_path /spool/nginx/client_temp 1 2; 存储临时文件的路径就是 /spool/nginx/client_temp/7/45/00000123457 client_body_in_file_only 这个配置是用于决定 Nginx 是否将客户端请求正文整个写入到临时文件当中。 client_body_in_file_only on | clean | off; 当它的配置指令值设置为 on 时请求处理结束后不会删除临时文件。当指令值设置为 clean 时请求处理结束后会删除临时文件。设置为 off 就是不记录到文件中啦默认值是 off 。 好了结合上面三个配置我们进行一波测试。 // nginx.conf
#client_body_buffer_size 10;
client_body_temp_path client_body_temptest;
client_body_in_file_only on; 先忽略第一个因为我们开启了 client_body_in_file_only 所以所有的请求体中的内容都会被记录。指定的目录是当前运行 Nginx 的目录下面的 client_body_temptest 目录其实就是给默认目录后面加了个 test 。接着咱们还需要定义一个可以发送 POST 请求的动态页面由于目前的环境还没有安装 PHP 所以咱们就随便代理一个地址。如果直接使用 POST 请求静态页面会报出 405 错误Nginx 默认是禁止 POST 静态页面的 location /request_body {proxy_pass http://localhost:8001;
} 注意哦这是我们随便代理的8001 是不存在的因此直接访问这个页面是会报错的。接下来用 Postman 发送一个 Post 请求使用哪种参数形式都可以这里我使用的是 raw 。 请求之后就可以看到 Nginx 的运行目录下多了个 client_body_temptest 目录进去后就看到了下面这样的内容。 // POST 请求 http://192.168.56.88/request_body 之后
// /usr/local/nginx/client_body_temptest
[rootlocalhost client_body_temptest]# ll
total 140
-rw-------. 1 www www 60453 Jul 30 03:13 0000000001 试着打开文件你就会发现里面正是我们发送请求时写在请求体中的内容。好了接下来怎么测 client_body_buffer_size 呢它的意思是当请求体的大小超过了设置的缓冲值时使用文件来保存请求体内容。注意我们现在开启了 client_body_in_file_only 因此所有文件都被保存下来所以我们要注释掉它然后再打开 client_body_buffer_size 的注释并把值设小点。 // nginx.conf
client_body_buffer_size 10;
client_body_temp_path client_body_temptest;
#client_body_in_file_only on; 再次请求页面在 client_body_temptest 目录下并没有生成新的文件这要怎么验证呢其实很简单用 ll -a 看一下当前目录的修改时间就好了或者再次开启 client_body_in_file_only 会发现文件序号其实一直在增长。 // POST 请求 http://192.168.56.88/request_body 之后
// /usr/local/nginx/client_body_temptest
[rootlocalhost client_body_temptest]# ll -a
total 20
drwx------. 2 www root 24 Jul 30 03:30 .
drwxr-xr-x. 11 root root 167 Jul 30 02:31 ..
-rw-------. 1 www www 18074 Jul 30 03:13 0000000001 第一个 . 表示当前目录看到它的修改时间发生了变化。现在你再把 client_body_buffer_size 的值调大只要大过你测试的请求体的长度就好了。完了再测试一下看看这个目录的修改时间会不会发生变化。如果没有发生变化就说明请求体在缓冲中处理了没有在这里创建过临时文件。 上面三个配置要注意的几点是 client_body_temp_path 指定的目录要有 Nginx 运行用户的权限就是我们第一篇文章中那个 user 指定的用户。出现 xxx upstream response is buffered to a temporary file xxxx while reading upstream 这样的错误就是请求体频繁使用文件存储可能是 client_body_buffer_size 的值设小了可以适当调大具体大小根据内存占用情况来确定。如果不在乎内存就把 client_body_buffer_size 和后面要讲的 client_max_body_size 设置成一样完全不走文件保存了。client_body_in_file_only 非调试测试的情况下不要开完全走文件肯定影响效率。 client_body_in_single_buffer 这个配置项可以确定 Nginx 将整个客户端请求正文是否保存在一块缓冲中。 client_body_in_single_buffer on | off; 它的默认值是 off 推荐在使用 $request_body 变量时使用可以节省引入的拷贝操作。 client_body_timeout 用于定义读取客户端请求正文的超时时间。 client_body_timeout time; 默认值是 60 秒超时是指相邻两次读操作之间的最大时间间隔而不是整个请求正文完成传输的最大时间。如果客户端在这段时间内没有传输任何数据Nginx 将返回408Request Time-out 错误到客户端。啥意思呢连接建立了60s 内啥玩意也不发直接就报错呗这个我也不知道怎么测所以咱们保持默认就好啦。 client_max_body_size 它设置允许客户端请求正文的最大长度这个配置应该是比较常见的特别是做过上传大文件的同学。 client_max_body_size size; 它的默认值是 1m 和 PHP 中的 upload_max_filesize 以及 post_max_size类似不过 PHP 中的默认值是 2m 。如果要上传大文件这两边都要修改。请求的长度由 “Content-Length” 请求头指定。如果请求的长度超过设定值nginx将返回错误 413Request Entity Too Large到客户端。请注意浏览器不能正确显示这个错误。设置成 0 可以使nginx不检查客户端请求正文的长度。 这个好测直接找个大于 1m 的文件用 POST 上传到我们前面那个 /request_body 路径下然后再修改这个值超过我们选择的文件大小再试一次就知道它的效果啦或者直接设置成小的值比如 1k 然后随便找个大于 1k 的测试一下会不会返回 413 错误。 请求限流 Nginx 的请求限流部分主要限的是速度也就是流量大小。注意这里是限流不是限制限制是限制请求的连接数量 后面还有专门的请求限制模块。限流这里最典型的案例就是百度网盘的会员和非会员的下载速度的区别。通过 Nginx 我们也可以方便地对我们自己的流量速度进行限制我们先来看看这个配置相关的指令。 limit_except 在指定的 location 下面配置 limit_except 后可以按指定的 HTTP 方法进行请求限制。 limit_except method ... { ... } 在 Apache 下配置虚拟主机的时候经常会有 Deny 和 Allow 这些相关的配置而在 Nginx 中其实我们通常很少去配置这个。毕竟在 Apache 下面大部分情况下通常我们也是直接 Allow all; 的。 method 参数是用于指定不由这些限制条件进行过滤的 HTTP 方法可选值有 GET、 HEAD、 POST、 PUT、 DELETE、 MKCOL、 COPY、 MOVE、 OPTIONS、 PROPFIND、 PROPPATCH、 LOCK、 UNLOCK 或者 PATCH。 指定 method 为 GET 方法的同时Nginx 会自动添加 HEAD 方法。那么其他 HTTP 方法的请求就会由指令引导的配置块中的ngx_http_access_module 模块和 ngx_http_auth_basic_module 模块的指令来限制访问。这两个模块我们后面会单独学习。 那么咱们就来配置一个。为了能够测试 POST 之类的请求需要连接一下 PHP 所以咱们就使用之前配置好的 PHP 配置。 location ~ \.php$ {root html;limit_except GET {allow 192.168.56.101;deny all;}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;
} 在 html/1.php 这个文件中我们直接打印了 $_SERVER 的信息因此正常访问的话会输出 PHP 这边的 SERVER 相关内容这里就不多说了。 我们的主机是虚拟机的主机IP 是 192.168.56.1 在配置中我们 deny 了 all 但是开放了 .101 可以访问。划重点了上面的 GET 表示除了 GET 之外的比如 POST 之类的请求就会走下面的限制约束第一次接触的小伙伴可能真的会搞反以为是写在这里的才被限制其实是反过来的哦写在这里的是不被限制的。因此在现在的情况下.1 主机 GET 访问 http://192.168.56.88/1.php 应该是没问题了那么 POST 访问会出现什么呢 大家可以试试直接返回的就是 403 Forbidden 也就是没有权限。也就是说deny 是生效的。现在我们再开一台虚拟机IP 设置成 192.168.56.101 然后使用 CURL 请求。 // 192.168.56.101
[rootlocalhost ~]# curl -X POST http://192.168.56.88/1.php
Array
([USER] www[HOME] /home/www…………
) 没有任何问题POST 也可以正常请求说明 allow 对 .101 这台虚拟机是生效的。有兴趣的小伙伴可以再开一台虚拟机设置成别的 IP 再次进行测试看看效果怎么样。 limit_rate 接下来我们就来看看怎么限制流量这个配置也比较简单。 limit_rate rate; 默认值是 0 单位是 字节/秒 默认 0 就表示不限制。Nginx 按连接限速所以如果某个客户端同时开启了两个连接那么客户端的整体速率是这条指令设置值的 2 倍。 从 1.17.0 版本开始参数值可以包含变量如果要根据特定条件限制速率的话它可能很有用 map $slow $rate {1 4k;2 8k;
}limit_rate $rate; 另外我们也可以直接使用 $limit_rate 变量设置流量限制(1.17.0后不推荐)。如果想在特定条件下限制响应传输速率可以使用这个功能 server {if ($slow) {set $limit_rate 4k;}...
} 变量相关的内容我们在后面的文章中再详细说一会也会简单演示一下。 最后还可以通过 “X-Accel-Limit-Rate” 响应头来完成速率限制。这种机制可以用 proxy_ignore_headers 指令和 fastcgi_ignore_headers 指令关闭。 上面全是官网的说明内容具体的演示我们将结合下面的配置指令一起测试。 limit_rate_after 这个指令用于设置不限速传输的响应大小。 limit_rate_after size; 默认 0 单位是字节当传输量大于此值时超出部分将根据 limit_rate 的规则限速传送。 测试限流 好了咱们来试试吧。首先得搞个大点的文件这样传输过程才会持续一段时间就挑个之前我录过的视频好了。把它放到之前准备好的 /usr/local/nginx/html/mp4/ 目录下并改名为 1.mp4 为了好记好测。接着就配置一个 location 。 location /limitmp4 {alias /usr/local/nginx/html/mp4/;
} 现在访问 /limitmp4/1.mp4 会发现速度很快直接下载视频速度也很惊人毕竟咱们是在本地的虚拟机上。然后咱们就来进行限流。 location /limitmp4 {alias /usr/local/nginx/html/mp4/;limit_rate 1k;
} 配置 limit_rate 设置为 1k 之后重载 Nginx 并进行访问。很明显连播放都开始卡顿了下载速度也直接变慢了。 location /limitmp4 {alias /usr/local/nginx/html/mp4/;limit_rate 1m;limit_rate_after 1000m;
} 继续加上 limit_rate_after 限制到 1000m limit_rate 设置为 1m 也就是 1G 以上的文件才会限制流量再次访问速度又恢复到了之前的水平。现在你可以随意修改这两个参数了比如将 limit_rate_after 改成 200m 我们的文件有 500m 这时限速又开始了不过速度比限制在 1k 的时候要好很多因为现在的传输速度在 1m 。 接下来我们测试一下 $limit_rate 变量的限制效果。 #set $limit_rate 1k;
location /limitmp4 {alias /usr/local/nginx/html/mp4/;#limit_rate 1m;#limit_rate_after 400m;set $limit_rate 1k;
}
location /limitmp4_2 {alias /usr/local/nginx/html/mp4/;
} 直接设置一个 $limit_rate 变量并给其赋值为 1k 然后访问链接速度被限制了。然后我们开启另一个 location 速度正常可以看到 $limit_rate 也是有作用域范围的。现在可以再打开最上面的也就是在 server 作用域下的 $limit_rate 会发现 /limitmp4_2 也被限速成功。 最后 X-Accel-Limit-Rate 头是针对上游服务器的也就是反向代理或者负载均衡那边返回的内容是否将对应的响应头返回给客户端的这个不好测资料也不多大概了解一下就好啦。 说了这么半天到底限流的意义何在呢除了百度网盘那种收费的作用外限流还可以保护我们的带宽避免某一个连接将整台服务器的带宽占满比如我们下载东西的时候。另外就是在大促高并发的场景下保障后端程序带宽的稳定性同样也是避免带宽被占用挤压影响其它业务。 将来我们在学习更多架构方面知识的时候再来详细的研究吧目前我的认知只到这个水平反正 Nginx 中是有这个功能的这一点大家还是要牢记。 总结 今天的内容真正的配置指令没几个请求正文有六个请求限流只有三个更多的还是在进行一些测试。毕竟都是自己之前从来没怎么配过玩过的东西。而且我发现请求限流相关的内容还是非常有意思的对于大文件上传下载也有了一些想法直接用 Nginx 就可以避免带宽被某几个用户的大文件操作占满。确实还是收获满满各位别急后面还有好玩的东西呢千万别错过了。 参考文档 http://nginx.org/en/docs/http/ngx_http_core_module.html