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

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;

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

proxy_pass_request_body off;

可以将请求的body丢掉。

client_body_buffer_size 100;

上面说过,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;

Nginx处理响应的行为

响应不携带body

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

响应携带body

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

响应相关的指令:

proxy_buffer_size 8k;

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

postpone_output 0;

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

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

proxy_buffering off;

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

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

proxy_buffers           256 8k;

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

仔细读上面这段逻辑,基本就能猜到分2个维度来配置read_buf,使得Nginx配置者更大的灵活度,根据自己业务响应大小的分布来设置 这 2个值,节约内存,提示性能。

你可能感兴趣的:(nginx)