ngx_http_proxy_module是nginx众多反向代理模块中非常常用的一个,它接受客户端的http请求,再转发给上游服务器。nginx作为负载均衡服务器,它必不可少。对于一个请求,proxy 模块处理的流程大致可以分为以下几个步骤。
判断proxy缓存
proxy模块是在content阶段发生,对于一个到来的请求,首先会判断是否开启了proxy_cache,如果开启了缓存,并且命中会直接将缓存文件中对应的key的内容返回。通常会对一些变化不频繁的内容做缓存以减轻nginx和上游服务器的压力。
构造发送给上游的header与body
proxy模块提供了很多指令来改变发给上游请求的headers和body,比如proxy_set_header,proxy_set_body,proxy_request_pass_request,prxy_request_pass_headers等等。nginx会先根据这些指令的内容生成header和body。(客户端请求的headers是在请求的11个阶段开始之前nginx框架就接受了,因为设计到分配变量,选择server,location等等)
读取请求body
上一步提到了,客户端与nginx建立连接后,nginx不会立即与上游服务器建立连接,先生成header和body,如果用户发送的是一个post请求,那么nginx通常是会先将客户端请求的body读取完再建立连接(由proxy_request_buffering指令决定,而且不管proxy_set_body,proxy_pass_request_body这些指令的设置如何,用户请求的body肯定是要接受的,是否redefine或者丢弃是另外一回事),这么做的好处是对于并发支持有限的上游服务器,这是一种能提升并发能力的做法,举一个例子,先做以下假设
- 客户端的请求是上传一个文件,文件size比较大
- 客户端的上行带宽有限
- 上游服务器和nginx处于同一个内网中
这时候如果我们没有打开proxy_request_buffering,那么nginx会立即与上游服务器建立连接,然后边接受客户端的请求内容,边将内容发给上游,此时如果上游服务器的并发连接数比较小,而这个请求可能会很长,如果此时有多个这样的上传请求,那么上游服务器的并发能力就会下降。如果打开了buffering,那么nginx会等所有的上传文件内容都接受完,再建立连接发送给上游,那么这次请求处理的就很快(内网网速非常快)。这样虽然对客户端来说没有什么区别,但是却能提升上游服务器的并发能力。
选择服务器
在上一步打开proxy_request_buffering后,nginx接受完完整请求的body(body保存在临时文件中),nginx会根据upstream中指定的负载均衡算法来选择一台上游服务器提供服务。
建立连接,发送请求
确定了连接的上游服务器,nginx便开始根据指定的参数(比如max_conn,fail_timeout等TCP连接参数)与上游服务器建立连接,连接建立成功后就开始将客户端请求的内容转发给上游。
接受响应
上游服务器处理完请求,nginx开始接受响应,包括header和body(先是header再是body),这时又会有一个proxy_buffering来决定nginx的行为,如果打开了proxy_buffering,那么nginx会等接受完完整的上游响应body后(Tips:1.如果body小于proxy_buffers设置的大小,通常为64K,那么即使打开proxy_buffering,也不会保存到临时文件中。2. 如果上游服务器的响应headers里有X-Accel-Buffering: yes|no,会覆盖proxy_buffering的指值。 3.如果headers的大小大于proxy_buffer_size大小,或产生502错误),再发给客户端,通常nginx与上游都是在同一个内网中,所以这个配置是打开的。在这一步,nginx同样提供了很多指令来改变发给客户端的响应内容。
保存缓存
如果打开了proxy_cache,那么nginx会将响应内容保存到缓存文件中,cache的行为包括缓存文件的路径,缓存内容的key的规则,keys对应的共享内存的name和size等等都有不同的指令完成。
关闭或复用连接
上一步中,如果没有打开cache,那么nginx会根据upstream中keepalive指令来决定是否关闭或者复用tcp连接。
(tip: nginx作为负载均衡服务,通常与上游的连接数理论上最大为65535个(local port限制),如果想要提高并发数,增加上游服务的ip数量或者监听的端口数量来避开linux的系统限制)
以上就是proxy_module处理和转发请求的大致流程,其中有一些细节十分巧妙,nginx就是这样,在很多功能上的设计都是如此,这也是它越发流行的原因之一吧。