nginx反向代理模块


文字:

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一样的响应。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容