• 进入"运维那点事"后,希望您第一件事就是阅读“关于”栏目,仔细阅读“关于Ctrl+c问题”,不希望误会!

Nginx proxy模块相关指令

Nginx 彭东稳 8年前 (2016-05-22) 25673次浏览 已收录 0个评论

一、代理模块(ngx_http_proxy_module)

反向代理( reverse proxy) 方式是指用代理服务器来接受 Internet 上的连接请求, 然后将请求转发给内部网络中的上游服务器, 并将从上游服务器上得到的结果返回给 Internet 上请求连接的客户端, 此时代理服务器对外的表现就是一个 Web 服务器。 充当反向代理服务器也是 Nginx 的一种常见用法( 反向代理服务器必须能够处理大量并发请求), 下面将介绍Nginx作为 HTTP 反向代理服务器的基本用法。由于Nginx具有“强悍”的高并发高负载能力, 因此一般会作为前端的服务器直接向客户端提供静态文件服务。 但也有一些复杂、 多变的业务不适合放到 Nginx 服务器上, 这时会用Apache、 Tomcat 等服务器来处理。 于是, Nginx 通常会被配置为既是静态Web服务器也是反向代理服务器( 如下图所示), 不适合Nginx处理的请求就会直接转发到上游服务器中处理。

Nginx proxy模块相关指令

ngx_http_proxy_module模块允许传送请求到其它服务器,也就是做反向代理。下面提供一个基本的配置示例:

二、ngx_http_proxy_module模块常用指令

1)proxy_bind

在调用connect()前将上游socket绑定到一个本地地址,如果主机有多个网络接口或别名,但是你希望代理的连接通过指定的借口或地址,可以使用这个指令。

透明传输模式允许传出连接到代理服务器起源于一个非本地IP地址,例如,从一个真实的IP地址的客户端 ︰

为了使此参数工作,就必须以超级用户的特权运行nginx的工作进程和配置内核路由表拦截来自代理服务器的网络流量。

2)proxy_buffer_size

设置缓冲区的大小为size,nginx从被代理的服务器读取响应时,使用该缓冲区保存响应的开始部分。这部分通常包含着一个小小的响应头。该缓冲区大小默认等于proxy_buffers指令设置的一块缓冲区的大小,但它也可以被设置得更小。

3)proxy_buffers

设置用于读取应答(来自被代理服务器)的缓冲区数目和大小,为每个连接设置缓冲区的数量是number参数,每块缓冲区的大小是size参数。这些缓冲区用于保存从被代理的服务器读取的响应。每块缓冲区默认等于一个内存页的大小。这个值默认是4K还是8K,取决于平台。

4)proxy_buffering

代理的时候,开启或关闭缓冲后端服务器的响应。

当开启缓冲时,nginx尽可能快地从被代理的服务器接收响应,再将它存入proxy_buffer_size和proxy_buffers指令设置的缓冲区中。如果响应无法整个纳入内存,那么其中一部分将存入磁盘上的临时文件。proxy_max_temp_file_size和proxy_temp_file_write_size指令可以控制临时文件的写入。

当关闭缓冲时,收到响应后,nginx立即将其同步传给客户端。nginx不会尝试从被代理的服务器读取整个请求,而是将proxy_buffer_size指令设定的大小作为一次读取的最大长度。

响应头“X-Accel-Buffering”传递“yes”或“no”可以动态地开启或关闭代理的缓冲功能。 这个能力可以通过proxy_ignore_headers指令关闭。

5)proxy_busy_buffers_size

当开启缓冲响应的功能以后,在没有读到全部响应的情况下,写缓冲到达一定大小时,nginx一定会向客户端发送响应,直到缓冲小于此值。这条指令用来设置此值。 同时,剩余的缓冲区可以用于接收响应,如果需要,一部分内容将缓冲到临时文件。该大小默认是proxy_buffer_size和proxy_buffers指令设置单块缓冲大小的两倍。

6)proxy_max_temp_file

打开响应缓冲以后,如果整个响应不能存放在proxy_buffer_size和proxy_buffers指令设置的缓冲区内,部分响应可以存放在临时文件中。 这条指令可以设置临时文件的最大容量。而每次写入临时文件的数据量则由proxy_temp_file_write_size指令定义。

将此值设置为0将禁止响应写入临时文件。

7)proxy_temp_file_write_size

在开启缓冲后端服务器响应到临时文件的功能后,设置nginx每次写数据到临时文件的size(大小)限制。 size的默认值是proxy_buffer_size指令和proxy_buffers指令定义的每块缓冲区大小的两倍, 而临时文件最大容量由proxy_max_temp_file_size指令设置。

8)proxy_temp_path

定义从后端服务器接收的临时文件的存放路径,可以为临时文件路径定义至多三层子目录的目录树。 比如,下面配置

那么临时文件的路径看起来会是这样:

9)proxy_connect_timeout

设置与后端服务器建立连接的超时时间,应该注意这个超时一般不可能大于75秒。默认为60s,建议生产环境连接时间设置为1到2s。

10)proxy_http_version

设置代理使用的HTTP协议版本,默认使用的版本是1.0,而1.1版本则推荐在使用keepalive连接时一起使用。我接触的生产环境中都是设置http 1.1版本了。

11)proxy_ignore_client_abort

决定当客户端在响应传输完成前就关闭连接时,nginx是否应关闭后端连接。

12)proxy_pass

设置后端服务器的协议和地址,还可以设置可选的URI以定义本地路径和后端服务器的映射关系。 这条指令可以设置的协议是“http”或者“https”,而地址既可以使用域名或者IP地址加端口(可选)的形式来定义:

对于URI可选,一般情况下使用是不需要指定的,除非你需要的访问方式就是这样的。

也可以使用UNIX域套接字路径来定义,该路径接在“unix”字符串后面,两端由冒号所包围,比如:

如果proxy_pass没有使用URI,传送到后端服务器的请求URI一般客户端发起的原始URI,如果nginx改变了请求URI,则传送的URI是nginx改变以后的完整规范化URI:

如果proxy_pass使用了URI(/也算),当传送请求到后端服务器时,规范化以后的请求路径(原始请求URI)与location配置中的路径的匹配部分将被替换为proxy_pass指令中定义的URI,其实这种实现方式就是做虚拟路径代理,配置方式如下:

虚拟路径代理就是,比如说访问”http://127.0.0.1/path/uri”地址,当匹配到这个location之后,通过”proxy_pass http://127.0.0.1/”代理到后端时,一个新的URL就成了”http://127.0.0.1/uri”这样。其中的/path就称为虚拟路径,虚拟给用户的,后端没有真正的/path路径,这里要特别注意”proxy_pass http://127.0.0.1/”最后的”/”,如果没有这个”/”那么访问就会出现404,因为你没有给proxy_pass定义URI,所以不存在将规范化以后的请求路径(原始请求URI)与location配置中的路径的匹配部分将被替换为proxy_pass指令中定义的URI这一说法,切记。Nginx实现虚拟路径代理

注意

使用一个正则表达式(~或~*)指定localtion时种情况下,proxy_pass应该是一个没有URI的指令,如果指定了URI,那么代理到后端时,URI会被去掉,从而变成了http://127.0.0.1/some/path,也就是说原始访问URI不会做任何改变传送到后端。

还有一种情况,当URI使用rwrite重写指令后种情况下,proxy_pass应该是一个没有URI的指令,如果指定了URI,那么代理到后端时,URI会被去掉,从而变成了http://127.0.0.1/some/path。

最后,这种以代理的工作方式,一般都会使用到Nginx upstream,以此来做负载均衡。这种情况下直接给定一个upstream的名称即可(需要先定义一个upstream),如下:

13)proxy_next_upstream

当你使用Nginx proxy代理时,如果是代理到后端是使用upstream,那么这个指令就是指定在何种情况下,一个失败的请求应该被发送到下一台后端服务器,有如下指令:

error – 和后端服务器建立连接时,或者向后端服务器发送请求时,或者从后端服务器读取响应时,出现错误;

timeout – 和后端服务器建立连接时,或者向后端服务器发送请求时,或者从后端服务器读取响应时,出现超时;

invalid_header – 后端服务器返回空响应或者非法响应头;

http_500 – 后端服务器返回的响应状态码为500;

http_502 – 后端服务器返回的响应状态码为502;

http_503 – 后端服务器返回的响应状态码为503;

http_504 – 后端服务器返回的响应状态码为504;

http_404 – 后端服务器返回的响应状态码为404;

off –  关闭proxy_next_upstream功能—出错就选择另一台上游服务器再次转发。

需要理解一点的是,只有在没有向客户端发送任何数据以前,将请求转给下一台后端服务器才是可行的。也就是说,如果在传输响应到客户端时出现错误或者超时,这类错误是不可能恢复的。

另外Nginx1.7开始提供了将请求传递给下一台服务器可以通过重试的次数和时间进行限制。

14)proxy_next_upstream_timeout

限制了重试请求可以被传递给下一台服务器的时间,默认值为0将关闭这一限制。

15)proxy_next_upstream_tries

限制了重试请求可以被传递给下一台服务器的次数,默认值为0将关闭这一限制。

16)proxy_read_timeout

定义从后端服务器读取(接收)数据的超时时间(Nginx从客户端接收到请求,然后把数据包转发到后端服务器,后端服务器处理完请求后返回给Nginx服务器,Nginx接收后端数据包称为一次read),此超时是指相邻两次读操作之间的最长时间间隔,而不是整个响应传输完成的最长时间。如果后端服务器在超时时间段内没有传输任何数据,连接将被关闭。默认时间为60s,建议值为2-4s。

17)proxy_send_timeout

定义向后端服务器发送一次数据包的超时时间(Nginx从客户端接收到请求,然后把数据包转发到后端服务器称为一次send),此超时是指相邻两次写操作之间的最长时间间隔,而不是整个请求传输完成的最长时间。如果再向后端服务器发送数据包时,超过了超时时间的设置,那么连接将被关闭。默认时间为60s,建议值为2-4s。

18)proxy_set_header

允许重新定义或者添加发往后端服务器的请求头。value可以包含文本、变量或者它们的组合。 当且仅当当前配置级别中没有定义proxy_set_header指令时,会从上面的级别继承配置。 默认情况下,只有两个请求头会被重新定义:

如果不想改变请求头“Host”的值,可以这样来设置:

但是,如果客户端请求头中没有携带这个头部,那么传递到后端服务器的请求也不含这个头部。 这种情况下,更好的方式是使用$host变量——它的值在请求包含“Host”请求头时为“Host”字段的值,在请求未携带“Host”请求头时为虚拟主机的主域名:

此外,服务器名可以和后端服务器的端口一起传送:

如果某个请求头的值为空,那么这个请求头将不会传送给后端服务器:

一般我们的 Nginx 代理服务器有多层,比如两层 Nginx,那么对于第二层 Nginx 来说如果想获取客户端正确 IP 地址,那么就得在第一层Nginx添加客户端 X-Forwarded-For 请求头的了。比如:

对于第二层 Nginx 来说,就可以通过获取变量 $http_x_forwarded_for 来获取客户端请求头的 X-Forwarded-For 数据,也就是远程客户端地址。但更多的用法是使用 $proxy_add_x_forwarded_for 内置变量,如下:

它同样会将 $remote_addr 变量值添加在客户端 X-Forwarded-For 请求头的后面,并以逗号分隔。如果客户端请求未携带 X-Forwarded-For 请求头,则 $proxy_add_x_forwarded_for 变量值将与 $remote_addr 变量相同。这主要是因为你的第一层 Nginx 上面可能还有 CDN,一般 CDN 也会添加 X-Forwarded-For 数据,向下传递 $remote_addr。 这样你使用 $proxy_add_x_forwarded_for 就没有后顾之忧了,如果第一层 Nginx 上面不是客户端而是一个 CDN,那么你添加的 X-Forwarded-For 请求头会有 $remote_addr 变量信息以及 CDN 的 IP 地址,那么 X-Forwarded-For 的内容变成“客户端 IP,CDN IP”,如果是这种情况的话,那后端的程序通过 X-Forwarded-For 获得客户端 IP,则取逗号分隔的第一项即可。如果上层直接是客户端请求,那么 X-Forwarded-For 就直接获取到客户端 IP 地址了。

那么在 Nginx 日志格式中,获取 X-Forwarded-For 数据的变量是 $http_x_forwarded_for 变量;获取上层客户端地址的变量是 $remote_addr 变量;有时候还会看见 $http_x_real_ip 变量,是用来获取 X-Real-IP 请求头数据的变量。

19)proxy_pass_header

允许指定跳过某些字段从代理服务器到客户端,一般用在CDN中传回来的字段信息,但不需要传回到后端服务器,就可以使用proxy_pass_header指令跳过。

20)proxy_redirect

设置后端服务器“Location”响应头和“Refresh”响应头的替换文本。 假设后端服务器返回的响应头是 “Location: http://localhost:8000/two/some/uri/”,那么指令

将把字符串改写为 “Location: http://frontend/one/some/uri/”。

replacement字符串可以省略服务器名:

此时将使用代理服务器的主域名和端口号来替换。如果端口是80,可以不加。

用default参数指定的默认替换使用了location和proxy_pass指令的参数。因此,下面两例配置等价:

而且因为同样的原因,proxy_pass指令使用变量时,不允许本指令使用default参数。

replacement字符串可以包含变量:

而redirect字符串从1.1.11版本开始也可以包含变量:

同时,从1.1.11版本开始,指令支持正则表达式。使用正则表达式的话,如果是大小写敏感的匹配,redirect以“~”作为开始,如果是大小写不敏感的匹配,redirect以“~*”作为开始。而且redirect的正则表达式中可以包含命名匹配组和位置匹配组,而在replacement中可以引用这些匹配组的值:

除此以外,可以同时定义多个proxy_redirect指令:

另外,off参数可以使所有相同配置级别的proxy_redirect指令无效:

 


如果您觉得本站对你有帮助,那么可以支付宝扫码捐助以帮助本站更好地发展,在此谢过。
喜欢 (1)
[资助本站您就扫码 谢谢]
分享 (0)

您必须 登录 才能发表评论!