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会将header
和body
缓存,收完全部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
的值是对所有发送的响应数据都生效,包括header
和body
,但是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个值,节约内存,提示性能。