文字:
proxy模块
HTTP反向代理处理流程
proxy模块
功能:对上游服务器使用http/https协议进行反向代理。
语法:proxy_pass URL;
上下文:if,if in location
URL规则
必须以http或者https开头,接下来是域名|IP地址|Unix socket|upstream的名字。
域名和IP地址后边可以加端口。
最后可以带上可选的URI
URL参数中带有URI会导致法向上游的URL不同
不携带URI,则将客户端请求中的URL直接发送给上游服务器。
携带URI,则对用户请求中的URL做如下操作:
将location中匹配上的一段替换为该URI。
小例子:
upstreamproxyups {
server127.0.0.1:8012 weight=1;
keepalive2;
}
server{
set_real_ip_from 192.168.188.60;
real_ip_headerX-Forwarded-For;
listen8080;
location/a {
#proxy_passhttp://proxyups/www;
proxy_passhttp://proxyups;
proxy_http_version1.1;
proxy_set_headerConnection"";
}
上例中,我配置上游服务器,返回$uri的内容。
上边proxy_pass的配置下:curl 192.168.188.60:8080/a/c,会输出 uri:/a/c,会原封不动地把URI发送给上游服务器。
如果上边第一个proxy_pass的注释打开,注释掉第二条。curl 192.168.188.60:8080/a/c,会输出:uri:/www/c,在location中先进行URI替换,然后再发送给上游服务器。
根据指令修改发往上游的请求
生成发往上游的请求行
proxy_method指令
语法:proxy_method method;
上下文:http,server,location。
作用:设置传给上游服务器的http请求的方法。
proxy_http_version
语法proxy_http_version 1.0|1.1
默认:proxy_http_version 1.0;
如果使用keepalive功能的时候,就必须使用proxy_http_version 1.1。
proxy_pass_requests_headers
作用:是否把用户请求的头部发给上游。如果设置为off,那么就不再把用户请求的header发给上游服务器了。
默认:proxy_pass_requests_headers on;
proxy_pass_requests_body
作用:是否把用户请求的包体发给上游。
默认:proxy_pass_requests_body on;
proxy_set_header
默认:proxy_set_header Host $proxy_host; proxy_set_header Connection close;
作用:在上边proxy_pass_requests_headers为on的情况下,我可以自己设置传给上游服务器的header的头部内容。
proxy_set_body
作用:作用:在上边proxy_pass_requests_body为on的情况下,我可以自己设置传给上游服务器的body的内容。
小例子:
反向代理配置
upstreamproxyups {
server127.0.0.1:8012 weight=1;
}
server{
listen8080;
location/a {
proxy_passhttp://proxyups/www;
proxy_methodPOST;
# proxy_pass_request_headers off;
# proxy_pass_request_body off;
proxy_set_headerHost'yang';
proxy_set_body'helow world';
proxy_http_version1.1;
proxy_set_headerConnection"";
}
}
上游服务器配置
server{
listen8012;
return200'8012 server response
uri:$uri
method:$request_method
request:$request
Host:$Host
http_name:$http_name\n';
}
执行测试命令:curl -H 'name:yudalihua' 192.168.188.60:8080/a/b
我在反向代理中设置的header能够直接显示出来,但是设置的body内容需要抓包才能看到,使用如下命令在8012端口抓包:tcpdump -i lo port 8012 -A -s 0 ,就能够看到在反向代理模块设置的body内容“hello world”
接收用户请求包体的方式
proxy_request_bufferring
默认:proxy_request_bufferring on;
当设置为on的情况
客户端网速比较慢
上游服务并发处理能力低
适应高吞吐量的场景。
当设置为off的情况
更及时的响应
降低nginx读写磁盘的消耗。
一旦开始发送内容,proxy_next_upstream指令失效。
client_body_buffer_size
默认:client_body_buffer_size 8k|18k
原理:
在接收header的时候,可能会接收到部分body。
判断接收到的body是否已经是所有的body。
如果已经接收完了body,则不分配client_body_buffer
若剩余待接收包体长度小于client_body_buffer_size,则仅分配所需要的。
否则,我们就分配client_body_buffer_size 大小的内存,用于接收客户端的body。不管用户的body是1G还是多大,我们都是通过这么大小的缓存,一段一段地收。
client_body_in_single_buffer
client_max_body_size
默认:client_max_body_size 1m;
客户端body的最大长度,默认是1M,非常小,不够用。
作用:针对请求头部中含有Content-length时,如果其字段超过了client_max_body_size,就返回413错误。
client_body_temp_path
默认:client_body_temp_path client_body_temp;
client_body_in_file_only
语法:client_body_in_file_only on|clean| off;
默认:client_body_in_file_only off;
如果设置为on:
那么客户端的请求的body会被一直保存在文件中,方便我们定位问题。
如果设置为off:
那么客户端处理完body之后,可能该文件就被删除了。
client_body_timeout:
语法:client_body_timeout time;
默认:client_body_timeout 60s;
作用:两次读取body之间的最大时延,如果读取包体超过了最大时延,返回408错误。
与上游服务建立连接
proxy_connect_timeout
默认:proxy_connect_timeout 60s;
和上游建立TCP连接的超时时间。
如果超时了,上游肯定是没有响应的,那么nginx会生成一个502的响应码。
proxy_next_upstream http_502
作用:如果超时,或者其他原因,和一个上游服务器建立TCP连接出现错误,那么就选择另一个upstream进行尝试。
proxy_socket_keepalive
默认:proxy_socket_keepalive off;
作用:反向代理和上游服务是否开启TCP的keepalive功能。
上下文:http,server,location。
TCP的keepalive
判断TCP连接的对方是否存在,如果不存在,就及时关闭,减少资源的浪费。
keepalive
语法:keepalive connections
上下文:upstream
keepalive_requests
语法:keepalive_requests number;
默认:keepalive_requests 100;
上下文:upstream
proxy_bind
语法:proxy_bind address [transparent] |off;
address
address可以使用变量,例如$remote_addr
address可以使用非本机地址,但是必须加上transparent关键字。
作用:就是修改请求报文的IP头部中的source IP Address为我们指定的IP地址。
proxy_ignore_client_abort
默认:proxy_ignore_client_abort off;
如果设置为on:
当客户端到反向代理的连接断开的时候,忽略这种情况,不断开反向代理同上游服务器的连接。
会给上游带来很大的性能压力。
如果设置为 off:
当客户端和nginx断开连接的时候,nginx和上游服务器也断开连接。
默认为off。
proxy_send_timeout
默认:proxy_send_timeout 60s;
把请求发送给上游服务器,后请求的超时时间。
接收上游的响应
proxy_buffer_size
默认:proxy_buffer_size 4k|8k;
作用
限制了反向代理可以接收的上游的最大header,如果上游返回的响应有cookie等非常大的数据,可能会导致整个header超出了nginx处理的能力。
会报错,在错误日志文件中生成:upstream sent too big header
proxy_buffering
默认:proxy_buffering on;
如果设置为ON
那么nginx接收上游的服务发送来的响应body,会先缓存起来,然后再发送出去。
默认设置为ON,因为nginx和上游服务器都是在内网中,网速非常快。而nginx和客户端直接网速要慢很多,如果发送一个很大的body的话,那么会导致nginx和上游服务器有长时间的连接。而上游服务,比如Django,或者Tomcat的并发能力是非常弱的。
表明我们想要快速释放nginx和上游服务器之间的连接。
proxy_buffers
语法:proxy_buffers number size;
默认:proxy_buffers 8 4k|8k;
作用:
上个指令缓存上游的响应body的时候,要写到磁盘,就需要进行IO。
试想,如果我们不把上游的body放到磁盘中,而是放到缓存中可以吗?
这就是这个指令的效果,默认分配8个4k大小的缓存,也就是32k,如果这个缓存能够放下上游的body,就放到缓存中;否则,还是会向磁盘中写。
proxy_max_temp_file_size
默认:proxy_max_temp_file_size 1024m;
作用:
当把上游响应body写到磁盘的时候,限制这个磁盘文件大小的最大值。
如果超出了阈值,也会出错。
proxy_temp_write_sze
默认:proxy_temp_write_sze 8k|16k;
作用:当把上游的body写入磁盘的时候,每一次写磁盘,写进去的单位,一次8k或者16k。
proxy_temp_path
默认:proxy_temp_path proxy_temp;
作用:把上游的body写入磁盘时候,文件的路径。
proxy_busy_buffers_size
默认:proxy_busy_buffers_size 8k|16k;
作用:
及时转发body。
当从上游接收一个很大的response body的时候,会先把它写到磁盘或者缓存,但是每写好8k或者16k,就像客户端发送一次。
proxy_read_timeout
默认:proxy_read_timeout 60s;
作用:TCP层的概念,两次读取之间的超时时间是60秒,如果超过了这个事件,TCP连接应该就会断开了。
proxy_limit_rate
默认:proxy_limit_rate 0;
作用
限制读取上游响应的速度。
设置为0,表示不限制。
proxy_store
如果设置为on
nginx接收上游的响应body生成的临时文件,我们可以做持久化处理。
默认开启。
proxy_store access
设置上边持久化文件的访问权限。
小例子:
nginx配置
server{
listen8080;
root/tmp;
location/a {
proxy_passhttp://proxyups;
proxy_storeon;
proxy_store_accessuser:rw group:rw all:r;
}}
上游服务配置
server{
listen8012;
location/ {
roothtml;
}
}
curl 192.168.188.60:8080/a.txt 这个命令上游服务给我把a.txt文件发送过来了,按道理说我也设置了持久化了,但是不知道为什么,就是在nginx的机器上看不到把temp文件持久化的结果。
处理上游的响应
proxy_ignore_headers field ...;
功能:上游服务器的某些响应头可能会改变nginx的行为。这个指令可以让指定的响应头失效。
可以禁用功能的头部:
proxy_hide_header field;
功能:对于上游响应中的某些头部,设置默认不对客户端转发。
proxy_cookie_domain
proxy_cookie_path
上边两个指令都是nginx修改从上游服务器返回的Set-Cookie头部
proxy_redirect
nginx修改从上游服务器返回的响应中的location头部。
上游出现失败时的容错方案
proxy_next_upstream
前提:上游没有向客户端发送任何内容,哪怕一个字节。
配置:
error
与上游建立连接、读取响应、发送请求,等等,任何一个环境出现了错误,都可以满足条件,激活这个 命令。
timeout
命中 connetc_timeout 、 read_timeout等情景,会激活这个命令,重新选取一个upstream
invalid_header
收到的上游的HTTP的header是不合法的。
http_
可以跟一个明确的响应code。
可以根据这样的一个code去选择另一个upstream
off
不开启这个指令。
proxy_next_upstream_timeout
开始选用另一个upstream,直到选中某个upstream的超时时间。
proxy_next_upstream_tries
如果设置为0,表示不再限制。
小例子一:
nginx的配置
upstreamnextups {
server127.0.0.1:8012 weight=1;
server127.0.0.1:8011 weight=1;
}
server{
listen8080;
location/ {
proxy_passhttp://nextups;
proxy_connect_timeout1s;
proxy_next_upstream off;
}
上游服务器的配置
server{
listen8011;
return200'8011 server response\n';
}
server{
listen8014;
return200'8012 server response\n';
}
上边nginx中的upstream配置了两个服务,分别在8011和8012端口;我上游服务器没有开8012端口。
proxy_next_upstream 的值:
如果是off,执行curl 192.168.188.60:8080,可能会出错,因为请求还是会被分发到8012端口上,nginx可能等一定时间,就会向不存在的端口上发送请求,就会返回错误。
如果是error,当执行curl 192.168.188.60:8080时,不会返回错误,请求都被分发到了8012端口上了。
小例子二、
nginx的配置
server{
listen8080;
location/httperr {
proxy_next_upstream http_500;
proxy_passhttp://nextups;
}
上游服务的配置
server{
listen8011;
return200'8011 server response\n';
}
server{
listen8012;
return500'8012 system error\n';
}
执行curl 192.168.188.60:8080/httperr 命令,返回根据proxy_next_upstream的值
如果为http_500
那么所有的curl结果,都是8011 server response
如果为off,或者注释掉这一行
那么curl结果就是8011 server response 或者 8012 system error
proxy_intercept_errorson|off
默认为off。
作用:当上游响应的响应码>=300时,应该把响应返回客户端还是按照error_page指令处理。
总之来说,就是用error_page来拦截上游失败指令。
小例子:
nginx配置。
server{
listen8080;
error_page 500/a.txt;
location/intercept {
proxy_intercept_errorson;
proxy_passhttp://127.0.0.1:8012;
}
}
上游服务器配置
server{
listen8012;
return500'8012 system error\n';
}
上边设置了proxy_intercept_errors为on,那么curl 192.168.188.60:8080/intercep,上游服务器会返回500,这个500,被error_page拦截,进而执行了error_page的指令。
注意:error_page只能拦截返回值和他后边code一样的响应。