HTTP 协议反向代理中与上游服务端建立连接处理 描述:前面作者带着各位看友一起学习了 Nginx 反向代理以及接收客户端请求的处理相关指令参数,本小节将继续讲解在 Nginx 中与上游服务建立连接的一些重要指令参数配置。
指令参数
1.向上游服务器建立连接以及发送请求的超时时间控制:
proxy_connect_timeout 设置与上游服务建立连接的超时时间,缺省值 60s。如果在此时间内无法完成连接,则返回 502( Bad Gateway )错误终止,特别注意:超时设置通常 不能超过75秒 。 Syntax: proxy_connect_timeout time; Default: proxy_connect_timeout 60s; Context: http, server, location proxy_send_timeout 设置向上游服务发送请求的超时时间,缺省值 60s。如果在此时间内无法完成数据传输,则连接将关闭,并返回 504( Gateway Time-out )错误终止, 特别注意:超时仅在两个连续的写操作之间设置,而不是为整个请求的传输设置。 Syntax: proxy_send_timeout time; Default: proxy_send_timeout 60s; Context: http, server, location
2.当上游服务器建立连接异常时错误处理与故障转移
proxy_next_upstream 指令用于控制当上游服务出现错误时,是否尝试选择另一个上游服务器进行请求转发,简单来说,就是当上游返回失败时处理办法。缺省值为 error 以及 timeout ,其中 error 表示出现错误时重试; timeout 表示超时时重试; off 表示不进行故障转移,特别注意:其生效的前提是 Nginx 尚未向客户端发送任何响应字节,一旦已有数据发送,该机制将不再触发。 Syntax: proxy_next_upstream error | timeout | denied | invalid_header | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | http_429 | non_idempotent | off ...; Default: proxy_next_upstream error timeout; Context: http, server, location # 参数说明: error 当与上游建立连接、发送请求或读取响应过程中发生网络层面错误(如 TCP/IP 层错误)时触发重选; timeout 与与上游建立连接超时(connect timeout)、读取超时( read timeout)等场景下触发重选; denied 服务器拒绝连接(1.29.3)时; invalid_header 当与上游服务返回的 HTTP header 不合法时触发; http_xxx 服务器返回了指定的HTTP错误代码时; non_idempotent 根据 RFC 7231 规定,使用非幂等方法(POST,POST,PATCH)的请求不会被传递到下一个服务器,启用此选项明确允许重试此类请求时; off 禁止将请求传递到下一个服务器,即禁止 proxy_next_upstream 指令功能 proxy_next_upstream_timeout 指令用于限制将请求传递到下一个服务器的时间,若为 0 值则表示不限制时间。
proxy_next_upstream_tries 指令用于限制将请求传递到下一个服务器的尝试次数,若为 0 值则表示不限制重试次数。
Syntax: proxy_next_upstream_timeout time; Default: proxy_next_upstream_timeout 0; Context:http, server, location Syntax: proxy_next_upstream_tries number; Default: proxy_next_upstream_tries 0; Context: http, server, location proxy_intercept_errors 指令用于是否拦截来自上游的错误响应(状态码 ≥ 300)并使用 error_page 指令进行处理,缺省值 off 表示将上游服务原样返回给客户端,设置为 on 则会将错误响应替换为 Nginx 中通过 error_page 指令指定的错误响应码对应的页面。 Syntax: proxy_intercept_errors on | off; Default: proxy_intercept_errors off; Context: http, server, location 温馨提示:在 Nginx 中对于上游服务器连接异常处理重选机制是非常必要的,通常需要根据实际业务(在分布式部署场景)进行合理配置,以达到最佳的性能与稳定性。
3.为上游服务器连接时启用 keepalive 机制:分为 TCP keepalive 机制 与 HTTP keepalive 机制两部分。
3.1 TCP keepalive 机制
proxy_socket_keepalive 用于控制是否在连接上游服务器中启用 TCP keepalive 。默认情况下,操作系统的设置对套接字有效,缺省值 off 表示不启用;若设置为 on,则为套接字打开 SO_KEEPALIVE 套接字选项,有助于保持长连接状态,减少因网络抖动导致的频繁重连问题。
TCP 层的 keepalive 用于检测长时间空闲连接是否仍有效,由操作系统层面控制的,其探测原理是在设定的空闲时间后发送探测包,若对端正常,则响应探测应答;若主机或进程已不存在,则无响应或RST响应,从而识别并关闭失效连接,节省资源。 Syntax: proxy_socket_keepalive on | off; Default: proxy_socket_keepalive off; Context: http, server, location This directive appeared in version 1.15.6. 3.2 HTTP keepalive 机制:实际上在讲解 upstream 指令负载均衡服务组时已经提及,此处再复习回顾一下。
keepalive connections 指令用于设置每个 worker 进程维护的空闲 keepalive 连接数上限。 keepalive_requests number 指令用于设置单个 keepalive 连接最多可以处理的请求数,超过此值后将关闭该连接。 keepalive_timeout times 指令用于设置 HTTP keepalive 超时时间,即在上游服务器空闲状态下保持连接打开的最长时间。默认情况下 Nginx 不启用此功能,除非在 upstream 中明确设置了 keepalive 参数。
4.为上游服务器请求连接指定本地出口 IP 地址
proxy_bind 指令用于指定的本地IP地址发起到代理服务器的传出连接,这对于需要从特定网络接口或具有多个IP的机器上进行出站连接的场景非常有用,显式指定使用哪一个IP作为源地址发起连接,此外还可用于实现 IP 透传。 Syntax: proxy_bind address [transparent] | off; Default: — Context: http, server, location # 参数说明: transparent(1.11.0)允许从非本地IP地址(例如,从客户端的真实的IP地址)发起到被代理服务器的输出连接: proxy_bind $remote_addr transparent; proxy_bind_dynamic 指令是 Nginx 商业版本支持动态绑定,即在运行时根据上游服务器地址自动选择本地IP;启用后在每次连接尝试时进行绑定操作, Syntax: proxy_bind_dynamic on | off; Default: proxy_bind_dynamic off; Context: http, server, location This directive appeared in version 1.29.3. 温馨提示:虽然可用通过 proxy_bind 指令指定本地IP出口地址连接上游服务器,其本质是修改 outgoing TCP 连接IP头中的 source IP address , 此时上游服务器的请求来源即为指定的IP地址,所以在实践中务必保证上游返回的数据包能正确的路由返回 Nginx 服务器,否则连接无法继续。
weiyigeek.top-TCP数据包结构图
5.当客户端断开后的与上游服务器的连接控制
proxy_ignore_client_abort 指令用于当客户端在不等待响应的情况下关闭连接时,是否应关闭与代理服务器的连接。默认情况下(off),如果客户端在读取响应之前关闭了连接,Nginx 会立即终止与上游服务器的连接并返回给客户端一个错误,特别注意: 若启用可能增加上游服务器负担,需谨慎使用。 Syntax: proxy_ignore_client_abort on | off; Default: proxy_ignore_client_abort off; Context: http, server, location
示例演示
示例1.在 Nginx 实现反向代理时,当连接上游异常自动切换节点以及自定义上游服务错误响应码页面。
步骤 01.在 213 主机( openresty/1.27.1.1 )搭建一个简单的上游服务,分别创建 8010 和 8011 监听端口,用于演示上游正常返回 200 响应码,以及模拟异常响应码 500 # 10.20.172.213 主机 vim /usr/ local /openresty/nginx/conf/nginx.conf http { ... server { listen 8010; server_name localhost _; default_type text/plain; # 返回 200 响应码 return 200 "Response 200, this is upstream server on port $server_addr : $server_port \n" ; } server { listen 8011; server_name localhost _; default_type text/plain; # 返回 500 错误响应码 return 500 "Response 500, this is upstream server on port $server_addr : $server_port \n" ; } ... } # 配置修改完成后重载 openresty nginx -s reload 步骤 02.在 214 主机 Nginx 配置目录中创建 backend_server.conf 文件,定义 upstream 服务组。 tee /usr/ local /nginx/conf.d/backend_server.conf << 'EOF' # 创建上游服务器 upstream backend_server { # 定义共享内存区,用于在工作进程间同步负载信息,可根据后端服务器数量调整。 zone backend_zone 64k; # 多个上游服务组,缺省使用轮询负载均衡算法 server 10.20.172.213:8010; server 10.20.172.213:8011; # 设置与上游服务器的长连接,最多保持10个空闲的保活连接。 keepalive 10; keepalive_timeout 60s; # 设置与上游服务器的长连接,空闲连接的超时时间。 } EOF 步骤 03.在 214 主机的 Nginx 配置目录中创建 proxy_server.conf 文件,用于配置反向代理连接到上一个步骤中的上游服务组 backend_server 。 # 创建用于显示 500 错误的自定义页 echo "error_page HTTP 500 Internal Server Error" > /usr/ local /nginx/html/error_500.txt # 创建监听用于反向代理 tee /usr/ local /nginx/conf.d/proxy_server.conf << 'EOF' server { listen 80; server_name test.weiyigeek.top; access_log /var/ log /nginx/test.log main; error_log test.error.log debug; # 反向代理配置,将请求转发到上游服务器组 location / { proxy_pass http://backend_server; # 设置请求头部 proxy_set_header Host $host ; proxy_set_header X-Real-IP $remote_addr ; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ; # 启用长连接 proxy_set_header Connection "" ; proxy_http_version 1.1; # 关键点:关闭连接异常自动切换节点,缺省是 error timeout 时自动切换到下一个节点。 proxy_next_upstream off; } # 反向代理配置,用以验证连接异常自动切换节点。 location /error { proxy_pass http://backend_server; proxy_set_header Host $host ; proxy_set_header X-Real-IP $remote_addr ; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ; # 关键点:将连接超时设置为1秒,用以模拟连接异常。 proxy_connect_timeout 1s; # 关键点:设置当上游服务连接超时,异常响应头,以及返回500错误时,自动切换到下一个节点。 proxy_next_upstream error timeout invalid_header http_500; } # 反向代理配置,用以验证上游服务响应 500 错误码的自定义页面。 location /intercept { proxy_pass http://backend_server; proxy_set_header Host $host ; proxy_set_header X-Real-IP $remote_addr ; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ; # 启用拦截上游服务响应错误码 proxy_intercept_errors on; # 关闭连接异常自动切换节点。 proxy_next_upstream off; } # 指定500响应码,默认页面 error_page 500 /error_500.txt; location =/error_500.txt { root html/; } } EOF 步骤 04.配置修改完毕后执行 nginx -t 命令验证配置是否正确,再执行 nginx -s reload 命令重载 nginx,同样使用 curl 命令模拟访问,用于测试上游服务在连接异常以及特定的上游响应码的相关指令处理效果。 验证1.访问两次 / 路径,第一次正常返回上游服务端口信息,第二次正常返回上游服务异常(500)响应码,之后再修改 213 主机中 8011 端口为 8012 端口,用以模拟上游服务异常。
# 第一次访问正常返回上游服务端口信息,第二次访问模拟异常返回500错误码。 $ curl -i http://test.weiyigeek.top $ curl -i http://test.weiyigeek.top HTTP/1.1 500 Internal Server Error Server: nginx/1.29.0 Date: Wed, 10 Dec 2025 07:30:00 GMT Content-Type: text/plain Content-Length: 65 Connection: keep-alive Response 500, this is upstream server on port 10.20.172.213:8011 # 在213主机中将8011端口修改为8012后执行,用以模拟上游服务异常。 $ curl http://test.weiyigeek.top $ curl http://test.weiyigeek.top <html> <head><title>502 Bad Gateway</title></head> <body> <center><h1>502 Bad Gateway</h1></center> <hr><center>nginx/1.29.0</center> </body> </html> weiyigeek.top-验证1上游服务连接失败时图
验证2.访问 /error 路径,用以验证连接异常,之后再将 213 主机中 8012 端口改回到 8011 端口,以验证上游返回的响应为指定的 500 时( http_500 )自动切换节点到 10.20.172.213:8010 。
# 连接异常自动切换节点,不会再显示 502 Bad Gateway 了 [root@weiyigeek_top conf.d] # curl http://test.weiyigeek.top/error Response 200, this is upstream server on port 10.20.172.213:8010 [root@weiyigeek_top conf.d] # curl http://test.weiyigeek.top/error Response 200, this is upstream server on port 10.20.172.213:8010 # 上游返回500错误码时自动切换,不会再显示 Response 500, this is upstream server on port 10.20.172.213:8011 [root@weiyigeek_top conf.d] # curl http://test.weiyigeek.top/error Response 200, this is upstream server on port 10.20.172.213:8010 [root@weiyigeek_top conf.d] # curl http://test.weiyigeek.top/error Response 200, this is upstream server on port 10.20.172.213:8010
验证3.访问 /intercept 路径,验证拦截上游服务( backend_intercept )响应错误码,用以验证自定义错误页面,由图可知,等一次请求到上游 10.20.172.213:8010 中返回的 200,而第二次请求到上游 10.20.172.213:801 中返回的 500 状态码,遂返回自定义500 错误页面。
$ curl http://test.weiyigeek.top/intercept -i weiyigeek.top-拦截上游服务错误自定义错误页面图
至此,当前阶段已完成 Nginx 于上游服务器连接建立、请求发送,以及连接异常时处理等相关性能指令介绍,并实践了当连接上游异常时自动切换节点,和拦截上游响应错误码实现 error_page 自定义错误,从而有效处理上游故障和不良响应,增强系统的健壮性和透明性。
阅读原文:https://mp.weixin.qq.com/s/w-zbtv32farSz4aOe6zM_g
该文章在 2025/12/13 12:24:33 编辑过