Nginx的proxy_buffer

作者: veaxen 分类: Nginx 发布时间: 2019-01-09 22:29

前言

我们的一个项目中,原本是没有nginx做反向代理的,但是最近需要用 openresty 做一个网关,就在后端程序之前加了 nginx ,在测试服务器中,部署好网关和后端服务器程序之后,经过和客户端同学的沟通(沟通成本有点高啊,迟迟定位不到问题,可能也是经验不足),发现当传输的数据量大于 108kb 的时候,数据总是传输不全,检查完后端程序代码是没问题之后,怀疑是 nginx 的问题。 通过 nginx 日志:

2019/01/07 10:41:28 [crit] 32763#0: *5439 open() "/data/apps/openrestry/proxy_temp/5/02/0000000025" failed (13: Permission denied) whil
e reading upstream, client: xxx.xxx.xxx.xxx, server: xxx.xxx.cn, request: ....

发现原来是由于 nginx 没有权限创建和读取缓存文件,导致数据传输过程中断。

查看 nginx 运行权限:

[root@test-openresty ~]# ps -ef | grep nginx
root      9028 24620  0 21:40 pts/3    00:00:00 grep --color=auto nginx
root      9160     1  0  2018 ?        00:00:00 nginx: master process /usr/bin/openresty -p /data/apps/openresty -c /data/apps/openresty/nginx.conf
nobody 25878  9160  0 17:21 ?        00:00:00 nginx: worker process
nobody 25879  9160  0 17:21 ?        00:00:00 nginx: worker process
nobody 25880  9160  0 17:21 ?        00:00:00 nginx: worker process
nobody 25881  9160  0 17:21 ?        00:00:00 nginx: worker process

发现 nginx worker 用的是nobody权限在运行,而 /data/apps/openrestry/proxy_temp 目录是root用户所有,干脆就新建一个 openrestry 用户,并将相应目录的所有权改为 openrestry 用户所有,更改 nginx 配置文件,让 nginx worker 以 openrestry 用户权限运行。

这样就解决了数据太大,被中断的问题了。但是,如果频繁在磁盘创建缓冲文件,势必让 nginx 吞吐量大降。这就是本文想要讲的 proxy_buffer

proxy_buffer的作用

如果没有buffer,数据将直接从 nginx 传输到客户端,假设客户端的加载速度足够快,那么是可以把proxy buffer给关掉的,让数据尽快到达客户端。

若使用proxy buffer,nginx将会临时存储后端response到缓冲区,然后慢慢把数据发送到客户端,启用buffer 的好处在于可以把数据一次性的发送给目标,相较于即时传输可以节约出部分带宽。

proxy_buffer的配置

proxy_buffer 是用于 proxy 模式(一般也可称为反向代理)的 buffer 配置。

下面简单记录下 nginx buffer 设置:

  • proxy_buffer_size 4k;
  • proxy_buffering on;
  • proxy_buffers 4 4k;
  • proxy_busy_buffers_size 8k;
  • proxy_max_temp_file_size 1024m;
  • proxy_temp_file_write_size 20m;

以上这些参数都是针对每一个http请求的,不是全局设置,比如proxy_buffer_size为4k,代表每一个请求都是4k,而不是所有请求共用4k

proxy_buffer_size

语法: proxy_buffer_size the_size
默认值: proxy_buffer_size 4k/8k
上下文: http, server, location

该指令设置缓冲区大小,从代理后端服务器取得的第一部分的响应内容,会放到这里.小的响应header通常位于这部分响应内容里边.
默认来说,该缓冲区大小等于指令 proxy_buffers所设置的;但是,你可以把它设置得更小.

proxy_buffering

语法: proxy_buffering on|off
默认值: proxy_buffering on
上下文: http, server, location

这个参数用来控制是否打开后端响应内容的缓冲区,如果这个设置为off,那么proxy_buffers和proxy_busy_buffers_size这两个指令将会失效。 但是无论proxy_buffering是否开启,对proxy_buffer_size都是生效的。

proxy_buffering开启的情况下,nignx会把后端返回的内容先放到缓冲区当中,然后再返回给客户端(边收边传,不是全部接收完再传给客户端)。 临时文件由proxy_max_temp_file_size和proxy_temp_file_write_size这两个指令决定的。如果响应内容无法放在内存里边,那么部分内容会被写到磁盘上

如果proxy_buffering关闭,那么nginx会立即把从后端收到的响应内容传送给客户端,每次取的大小为proxy_buffer_size的大小,这样效率肯定会比较低。

注意:
1. proxy_buffering启用时,要提防使用的代理缓冲区太大。这可能会吃掉你的内存,限制代理能够支持的最大并发连接数。
2. 对于基于长轮询(long-polling)的 Comet 应用来说,关闭 proxy_buffering 是重要的,不然异步响应将被缓存导致 Comet 无法工作

proxy_buffers

语法: proxy_buffers the_number is_size;
默认值: proxy_buffers 8 4k/8k;
上下文: http, server, location

该指令设置缓冲区的大小和数量,从被代理的后端服务器取得的响应内容,会放置到这里. 默认情况下,一个缓冲区的大小等于内存页面大小,可能是4K也可能是8K,这取决于平台。

proxy_buffers由缓冲区数量和缓冲区大小组成的。总的大小为number * size。

若某些请求的响应过大,则超过_buffers的部分将被缓冲到硬盘(缓冲目录由_temp_path指令指定), 当然这将会使读取响应的速度减慢, 影响用户体验. 可以使用proxy_max_temp_file_size指令关闭磁盘缓冲.

proxy_busy_buffers_size

语法: proxy_busy_buffers_size size;
默认值: proxy_busy_buffers_size proxy_buffer_size * 2;
上下文: http, server, location, if

proxy_busy_buffers_size不是独立的空间,他是 proxy_buffers 和 proxy_buffer_size 的一部分。nginx会在没有完全读完后端响应的时候就开始向客户端传送数据,所以它会划出一部分缓冲区来专门向客户端传送数据(这部分的大小是由proxy_busy_buffers_size来控制的,建议为proxy_buffers中单个缓冲区大小的2倍),然后它继续从后端取数据,缓冲区满了之后就写到磁盘的临时文件中。

proxy_max_temp_file_size和proxy_temp_file_write_size

临时文件由proxy_max_temp_file_size和proxy_temp_file_write_size这两个指令决定。 proxy_temp_file_write_size是一次访问能写入的临时文件的大小,默认是proxy_buffer_size和proxy_buffers中设置的缓冲区大小的2倍,Linux下一般是8k.

proxy_max_temp_file_size指定当响应内容大于proxy_buffers指定的缓冲区时, 写入硬盘的临时文件的大小. 如果超过了这个值, Nginx将与Proxy服务器同步的传递内容, 而不再缓冲到硬盘. 设置为0时, 则直接关闭硬盘缓冲

注意要点

首先第一个概念是所有的这些proxy buffer参数是作用到每一个请求的。每一个请求会安按照参数的配置获得自己的buffer。proxy buffer不是global而是per request的。

proxy_buffering 是为了开启response buffering of the proxied server,开启后proxy_buffers和proxy_busy_buffers_size参数才会起作用。

无论 proxy_buffering 是否开启,proxy_buffer_size(main buffer)都是工作的,proxy_buffer_size 所设置的 buffer_size 的作用是用来存储 upstream 端 response 的 header。

在proxy_buffering 开启的情况下,Nginx将会尽可能的读取所有的upstream端传输的数据到buffer,直到proxy_buffers设置的所有buffer们被写满或者数据被读取完(EOF)。此时nginx开始向客户端传输数据,会同时传输这一整串buffer们。同时如果response的内容很大的话,Nginx会接收并把他们写入到temp_file里去。大小由 proxy_max_temp_file_size 控制。如果busy的buffer传输完了会从temp_file里面接着读数据,直到传输完毕。

一旦proxy_buffers设置的buffer被写入,直到buffer里面的数据被完整的传输完(传输到客户端),这个buffer将会一直处在busy状态,我们不能对这个buffer进行任何别的操作。所有处在busy状态的buffer size加起来不能超过proxy_busy_buffers_size,所以proxy_busy_buffers_size是用来控制同时传输到客户端的buffer数量的。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据