nginx 均衡负载配置proxy_request_buffering 降低ttfb

27 3月

nginx 均衡负载配置proxy_request_buffering 降低ttfb

sendfile        on;
    tcp_nopush     on;
    tcp_nodelay    on;

    #keepalive_timeout  0;
    keepalive_timeout  60;
    keepalive_requests 200;

    ####gzip###########
    gzip  on;
    gzip_disable "msie6";
    # gzip_static on;
    gzip_proxied any;
    gzip_min_length 1000;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_buffers 64 4k;
    gzip_http_version 1.0;
    gzip_vary on;

    client_header_timeout 10;
    client_body_timeout 10;
    client_header_buffer_size 4k;
    client_body_buffer_size 4m;
    client_max_body_size 4m;
    large_client_header_buffers 4 32k;
    proxy_request_buffering off;
    client_body_postpone_size 4m;
    client_body_buffers 128 32k;

    reset_timedout_connection on;
    send_timeout 20s;

    #set default charset
    charset UTF-8;

    #http proxy
    proxy_connect_timeout 10;
    proxy_read_timeout 10;
    proxy_send_timeout 5;
    proxy_buffer_size 8k;
    proxy_buffers 128 32k;
    proxy_busy_buffers_size 512k;
    #proxy_temp_file_write_size 128k;
    proxy_http_version 1.1;
    proxy_upstream_tries 2;
    proxy_next_upstream http_500 http_502 http_504 error timeout invalid_header;
    proxy_cache_use_stale http_500 http_502 http_504 error timeout invalid_header updating;
    proxy_ignore_headers Expires Cache-Control Set-Cookie X-Accel-Expires;
    proxy_cache_lock on;
    proxy_cache_lock_age 5s;
    proxy_cache_lock_timeout 5s;
    proxy_set_header Connection "";

    location / {
        proxy_pass http://live_backend;
    }

upstream live_backend {
    server 10.2.95.84:80 max_fails=0;
    server 10.2.95.87:80 max_fails=0;
    keepalive 100;
    keepalive_timeout 60s;
    check interval=10000 fall=2 rise=3 timeout=5000 default_down=false type=tcp;
}

buffer ,即缓冲区,它在 Nginx 上发挥的作用就是 启用一个缓冲区,先在这个缓冲区内进行存储,再把数据发送出去 。和在线观看视频有点类似,先把视频文件缓冲一部分到本地再开始播放。

若没有 buffer,数据将会直接从 Nginx 传输到客户端。假设如果客户端的加载速度足够快,你可以直接把 buffer 关掉,让数据尽可能快地到达客户端。

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

顺带一提,Nginx 全局配置中的 tcp_nopush 的作用就是 数据包会累计到一定大小之后才会发送 。而 tcp_nodelay 是尽快发送数据,所以若你启用了 buffer,建议关闭 tcp_nodelay。

下面总结下 nginx buffer 设置:

12345proxy_buffer_size 4k;proxy_buffering on;proxy_buffers 4 4k;proxy_busy_buffers_size 8k;proxy_max_temp_file_size 1024m;

首先,这些参数都是针对每一个http request ,不是全局的。

proxy_buffer 的配置

proxy_buffer 是用于 proxy 模式(一般也可称为反向代理)的 buffer 配置。Nginx 有另外一种适用于 server 模式的 buffer 配置,这里本帖不做介绍。

proxy_buffer 包括了以下配置项:

需注意,以下指定的数值都是针对每一个 http request 的上限,而不是对于整个 buffer 区指定的上限。

proxy_buffering

1proxy_buffering on;

在 proxy_buffering 开启的时候,proxy_buffers 和 proxy_busy_buffers_size 才会起作用。

proxy_buffers

1proxy_buffers 4 8k;

指定一个 request 的 buffer 的数量和大小。

proxy_buffer_size

1proxy_buffer_size 4k;

指定后端 response 的 buffer 的大小。它是来自后端 response 的一部分,它包含 Headers,从 response 分离出来。它仅用于限定 headers 的 buffer 区,所以它的值比 proxy_buffers 更低。

proxy_buffer_size 有一点特殊在于,无论 proxy_buffering 是否开启,proxy_buffer_size 都会起作用。

proxy_busy_buffers_size

1proxy_busy_buffers_size 12k;

忙时 buffer 的最大值。一个客户端一次只能从一个 buffer 中读取数据的同时,剩下的 buffer 会被放到队列中,等待发送到客户端,这个 directive 指定在这个状态下的 buffer 的大小。

① 如果 proxy_buffers 关闭

Nginx不会尝试获取到后端服务器所有响应数据之后才返回给客户端,Nginx 会尽快把数据传给客户端,在数据传完之前,Nginx 接收到的最大缓存大小不能超过 proxy_buffer_size 。

② 如果 proxy_buffers 打开

Nginx将会尽可能的读取后端服务器的数据到buffer,直到proxy_buffers设置的所有buffer们被写满或者数据被读取完(EOF),此时Nginx开始向客户端传输数据,会同时传输这一整串buffer们。如果数据很大的话,Nginx会接收并把他们写入到temp_file里去,大小由proxy_max_temp_file_size 控制。「当数据没有完全读完的时候」,Nginx同时向客户端传送的buffer 大小 不能超过 proxy_busy_buffers_size 「此句可能理解有误」。

Nginx 作为反向代理(proxy)时的一些buffer指令

本将讲解了Nginx作为反代时一些行为的解释。
Nginx处理请求的行为

Nginx 只要配置的proxy_pass 都会无条件执行 ngx_http_read_client_request_body尝试去读 client 的 body。
请求不携带body

常见于 GET/HEAD方法。
此时,在ngx_http_read_client_request_body判断Content-length,如果没有或者值为0,则直接执行 ngx_http_upstream_init,即与后端建立连接。
请求携带body

常见于 POST 方法。
此时,Nginx在读完 header(即读完\r\n\r\n) 的时候,不会立刻连接到 upstream,而是需要在读完client完整的body的后才会继续执行ngx_http_upstream_init,即与此时才会去和upstream建立连接然后发送数据。
请求相关的指令:

proxy_request_buffering off;

1

可以使得Nginx及时没有读取完client body的时候,也能立刻连接upstream。换句话说,Nginx来了收到client的Header,就往upstream 连接并且发送。并且,来了部分的body,也会立刻转发到upstream,即所谓的流式上传。

proxy_pass_request_body off;

1

可以将请求的body丢掉。

client_body_buffer_size 100;

1

上面说过,Nginx默认会缓存请求body,那么缓存在哪里?一开始会保存在内存中,但是如果当前已经缓存的body大于client_body_buffer_size指定的大小,则把当前内存里面的body 存到 文件中。 Nginx对保存body的的数据结构是ngx_http_request_body_t:

typedef struct {
ngx_temp_file_t temp_file;/保存的目的文件*/
ngx_chain_t *bufs;/临时的bufs,filter 模块会使用/
ngx_buf_t buf;/根据 client_body_buffer_size 大小开辟的read_buf/ off_t rest;/表示还未接受到的数据长度,是content-length – alreadyread/
off_t received;
ngx_chain_t *free;
ngx_chain_t *busy;
ngx_http_chunked_t chunked; ngx_http_client_body_handler_pt post_handler;/如果数据读完,下一步走哪个流程*/
} ngx_http_request_body_t;

1
2
3
4
5
6
7
8
9
10
11

Nginx处理响应的行为
响应不携带body

header 会被 立刻转发给client,然后接结束了自己和upstream的连接,这个没什么好说的。
响应携带body

默认情况下,和请求类似,Nginx会将header和body缓存,收完全部body后,才一起将响应转发给client。
响应相关的指令:

proxy_buffer_size 8k;

1

Nginx使用该大小申请read_buf,即大小指定了 upstream header 最大长度,如果响应头超过了这个长度,Nginx会报upstream sent too big header错误,然后client收到的是502。

postpone_output 0;

1

Nginx在业务流程中,其实会立刻调用send去发送响应header。但是,在send的底层实现:ngx_http_write_filter中,因为postpone_output默认有值从而会将header延迟发送(不超过该阈值的数据会被缓存),直到有last标志位的buf出现才将所有的响应一次性发送(比如body最后一部分数据last会至上)。

postpone_output的值是对所有发送的响应数据都生效,包括header和body,但是Nginx业务流程中,处理body的时候,默认是不是立刻send的。所以,单单设置postpone_output为0,只是会将响应header 立刻发送至client,至于body怎么处理,看下面这些指令。

proxy_buffering off;

1

该指令将使得Nginx不对响应body进行缓存,收到upstream数据处理后,立刻调用send发送到client,即 响应流式转发。

那么,默认情况下,proxy_buffering是开着的,如果响应body很大,怎么办?

proxy_buffers 256 8k;

1

上述 两个指令只有在proxy_buffering开着的时候有效(默认就是开着的),其作用就是设置body的缓存大小。具体的意思是说,开辟 256个 长度为 8k大小的read_buf用来存储body,当然不是连接建立初始化时就开辟256个,而是当 当前buf不够存响应body时才会新申请一个,最多申请256个buf。

仔细读上面这段逻辑,基本就能猜到分2个维度来配置read_buf,使得Nginx配置者更大的灵活度,根据自己业务响应大小的分布来设置 这 2个值,节约内存,提示性能。
————————————————
版权声明:本文为CSDN博主「Mrpre」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mrpre/article/details/88034662

发表评论

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