Nginx - upstream 模块及参数测试

目录

- 1. 前言
- 2. 配置示例及指令说明
    - 2.1 配置示例
    - 2.2 指令
    - 2.3 upstream相关变量
- 3. 参数配置及测试
    - 3.1 max_fails 和 fail_timeout
    - 3.2 proxy_next_upstream
    - 3.3 nginx 与后端web连接时间的三个参数

1. 前言

  当 Nginx 作为反向代理使用的时候,upstream模块有着举足轻重的地位,官方解释:

  

2. 配置示例及指令说明

2.1 配置示例

2.2 指令

指令名称: upstream
语法:upstream name { … }
默认值:none
使用环境:http
功能:该指令是一个组合型指令它描述了一组服务器,这组服务器将会被指令 proxy_pass 和 fastcgi_pass 作为一个单独的实体使用,它们可以将 server 监听在不同的端口,而且还可以同时使用TCP和UNIX套接字监听。服务器可以设置不同的权重,如果没有设置权重,那么默认会将其设置为 1 。

指令名称: ip_hash
语法:ip_hash
默认值:none
使用环境:upstream
功能:如果使用了该指令,那么将会导致客户端的请求以用户端IP地址分布在 upstream 中的 server 之间。它的关键技术在于对这个请求客户端IP地址进行哈希计算,这种方法保证了客户端请求总是能够传递到同一台后台服务器,但是如果该服务器被认定为无效,那么这个客户端的请求将会被传递到其他服务器,因此,这种机制是一个高概率将客户端请求总是连接到同一台服务器。

Nginx 的 upstream 支持 5 种分配方式,其中有三种为 Nginx 原生支持的分配方式,后两种为第三方支持的分配方式。

  1. 轮询。upstream默认采用的就是轮询方式.
  2. 权重(weight)轮询模式的加强版,每个后端server 默认 weight=1
  3. ip_hash 每个请求按照访问IP的hash结果分配这样每个访客会固定访问一个后端服务器,可以解决session 一致问题
  4. fair 第三方分配方式。平地按照后端服务器的响应时间(rt)来分配请求,响应时间短即rt小的后端服务器优先分配请求。如果需要使用这种调度算法,必须下载Nginx的upstr_fair模块。
  5. url_hash 平地按照后端服务器的响应时间(rt)来分配请求,响应时间短即rt小的后端服务器优先分配请求。如果需要使用这种调度算法,必须下载Nginx的upstr_fair模块。

指令名称: server
语法:server name [parameters]
默认值:none
使用环境:upstream
功能:该指令用于设置服务器的 name,对于 name,可以使用域名、ip地址、端口或是 UNIX 套接字,如果一个域名被解析到多个 IP 地址,那么所有的 IP 地址都将会被使用。
可选的 parameters 如下:

  • weight=NUMBER   用于设置服务器的权重。如果没有设置,那么它将会等于 1
  • max_fails=NUMBER   该参数用于对后端服务器进行检测,如果达到 NUMBER 次数依然失败,则该 server 会被暂停 fail_timeout 秒,如果没有设置该参数,那么尝试的次数为1,如果设置为 0 则关闭检测。失败的依据是根据 proxy_next_upstream 提供的。
  • fail_timeout=TIME   该参数用于设置客户端到达 max_fails 次数后,该server 被暂停的时间。如果没有设置该参数,那么默认为 10秒。
  • down:如果为某一个 server 设置了该参数,那么标记了这台 server 将永久离线。通常这个参数与 ip_hash 一同使用。
  • backup:该参数在 0.6.7 版本中提供,它是一个备用标识,如果出现所有的非备份服务器全部宕机或繁忙无法接受连接时,那么才会使用本服务器,该参数无法和 ip_hash 指令一起使用。

2.3 upstream相关变量

变量名:$upstream_addr
功能:该变量表示了处理该请求的 upstream 中 server 的地址

变量名:$upstream_cache_status
功能:该变量出现在 Nginx 0.8.3 版本中, 可能的值如下:

  • MISS - 缓存中未被命中
  • EXPIRED - 生存期期满,请求被传递到后端服务器
  • UPDATING - 生存期满,陈旧的响应被使用,因为proxy/fastcgi_cache_use_stale 升级
  • STALE - 生存期期满,陈旧的响应被使用,因为 proxy/fastcgi_cache_use_stale
  • HIT - 缓存命中

变量名:$upstream_status
功能:该变量为 upstream 中 server 的响应状态

变量名:$upstream_response_time
功能:upstream server 响应的时间,单位为秒,能够精准到毫秒。如果有多个 server 响应回答,那么会用逗号和冒号分隔开

变量名:$upstream_http_$HEADER
功能:HTTP 协议头。例如:$upstream_http_host

3. 参数配置及测试

参数相关说明介绍完毕,接下来重点测试部分参数:

max_fails 、fail_timeout 、proxy_next_status

1台反向代理(nginx/1.14.2)
2台后端web(apache+php)

首先,查看客户端 发起一次 连接请求的过程:

通过抓包,可以看到 浏览器 请求一次 nginx 反向代理:

  • (9、10、11) 客户端 -> nginx TCP 三次握手成功
  • (12、13)12. 浏览器发起 GET 请求 13. 回复 ACK
  • (14、15、16)nginx -> 后端web服务 三次握手成功
  • (17、18) nginx 向后端web服务发起 get 请求, web服务ACK回复nginx
  • (19、20) 后端web服务返回请求数据给 nginx (这里返回HTTP状态为 304 Not Modified)
  • (21、22)nginx 连接后端服务采用的是HTTP1.0 ,后端服务主动发送FIN主动断开连接,后端web服务器从ESTABLISHED转为 TIME_WAIT
  • (23)nginx 将后端返回的结果,再返回给客户端浏览器

3.1 max_fails 和 fail_timeout

max_fails - 检测出错的次数。
fail_timeout - 出错后,暂停server的时间。

配置如下图:

主机信息:

nginx: 192.168.118.15
web1: 192.168.118.16
web2: 192.168.118.17

(1)当 max_fails 为 0 , fail_timeout 为 0

已知,upstream默认采用轮询的方式,web2服务关闭

通过浏览器快速刷新4次,分析如下:

首先查看 nginx 日志:

一共发起了 4 次连接请求,根据 upstream默认轮询方式,有两次都轮询到了 192.168.118.17 (服务关闭)上。

查看 web1(192.168.118.16)日志:

一共发起了 4 次请求,而 web1 接收到了 4 次,也就是这 4 次请求,都是 web1 来响应的。

为什么 4 次请求都是 web1 响应的呢?

通过上图,当 nginx 首次轮询到 web2 时,连接失败,web2 返回 RST,nginx会再次发起请求到 web1 。

总结:
max_fails = 0 and fail_timeout = 0 时,后端服务故障时,依然会轮询到故障主机,且没有暂停服务时间的限制。

(2) max_fails = 0 and fail_timeout = 5

已知,upstream默认采用轮询的方式,web2服务关闭, 配置如下:

通过浏览器快速刷新,分析如下:

nginx 日志

通过错误日志可以看出,当 upstream 没有设置 最大错误数(max_fails),无论后端server是否有效,都会轮询到该server上,fail_timeout 设置任何值都是无效的。

(3) max_fails = 3 and fail_timeout = 5

已知,upstream默认采用轮询的方式,web2服务关闭, 配置如下:

通过浏览器快速刷新,分析如下:

nginx 日志

通过配置最大失败连接数为 3 时,当后端web2服务关闭后,nginx首次会尝试 max_fails 次,如果仍然没响应,则暂停该server fail_timeout 秒,然后每隔 fail_timeout 时间后尝试一次,失败则继续暂停 fail_timeout 秒。

(4) max_fails = 3 and fail_timeout = 0

这种方式和 max_fails = 0 and fail_timeout = 3 测试结果一致,不在举例。

通过上面 max_fails 和 fail_timeout 测试,当要实现失败后暂停服务时,max_fails 和 fail_timeout 任何一项都不能为 0 。

在测试中,无论怎么刷新,nginx总是能够返回正常服务的server 数据,这是为什么?明明已经轮询到服务失效的节点,这里并没有定义任何的 proxy_next_upstream

解释:

针对nginx负载均衡upstream容错机制的使用说明

(1)nginx 的 upstream 容错

Nginx默认判断失败节点状态是以   和 timeout (上面的例子就为web2-timeout)状态为准,不以HTTP错误状态进行判断失败,因为HTTP只要能返回状态说明该节点还可以正常连接,除非添加了proxy_next_upstream指令设置对404、502、503、504、500和time out等错误进行转到备机处理。在next_upstream过程中,会对fails进行累加,如果备用机处理还是错误则直接返回错误信息(但404不进行记录到错误数,如果不配置错误状态也不对其进行错误状态记录)综述,nginx记录错误数量只记录timeout 、connect refuse、502、500、503、504这6种状态,timeout和connect refuse是永远被记录错误状态,而502、500、503、504只有在配置proxy_next_upstream后nginx才会记录这4种HTTP错误到fails中,当fails大于等于max_fails时,则该节点失效;

(2)nginx 处理节点失效和恢复的触发条件

nginx可以通过设置max_fails(最大尝试失败次数)和fail_timeout(失效时间,在到达最大尝试失败次数后,在fail_timeout的时间范围内节点被置为失效,除非所有节点都失效,否则该时间内,节点不进行恢复)对节点失败的尝试次数和失效时间进行设置,当超过最大尝试次数,则失效fail_timeout 时间,nginx每隔 fail_timeout时间尝试一次后端server 有没有恢复,直到所有后端服务失效,则返回错误页面给客户端;

(3)所有节点失效后 nginx 将重新恢复所有节点进行探测

如果探测所有节点均失效,备机也为失效时,那么nginx会对所有节点恢复为有效,重新尝试探测有效节点,如果探测到有效节点则返回正确节点内容,如果还是全部错误,那么继续探测下去,当没有正确信息时,节点失效时默认返回状态为502,但是下次访问节点时会继续探测正确节点,直到找到正确的为止。

(4)通过proxy_next_upstream实现容灾和重复处理问题

ngx_http_proxy_module 模块中包括proxy_next_upstream指令
语法: proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 |http_404 | off ...;
默认值: proxy_next_upstream error timeout;
上下文: http, server, location

error                   表示和后端服务器建立连接时,或者向后端服务器发送请求时,或者从后端服务器接收响应头时,出现错误
timeout                 表示和后端服务器建立连接时,或者向后端服务器发送请求时,或者从后端服务器接收响应头时,出现超时
invalid_header          表示后端服务器返回空响应或者非法响应头
http_500                表示后端服务器返回的响应状态码为500
http_502                表示后端服务器返回的响应状态码为502
http_503                表示后端服务器返回的响应状态码为503
http_504                表示后端服务器返回的响应状态码为504
http_404                表示后端服务器返回的响应状态码为404
off                     表示停止将请求发送给下一台后端服务器

运用场景:

1)proxy_next_upstream http_500 | http_502 | http_503 | http_504 |http_404;

当其中一台返回错误码404,500...等错误时,可以分配到下一台服务器程序继续处理,提高平台访问成功率,多可运用于前台程序负载设置

2)proxy_next_upstream off

因为proxy_next_upstream 默认值: proxy_next_upstream error timeout;

场景:

当访问A时,A返回error timeout时,访问会继续分配到下一台服务器处理,就等于一个请求分发到多台服务器,就可能出现多次处理的情况,如果涉及到充值,就有可能充值多次的情况,这种情况下就要把proxy_next_upstream关掉即可
proxy_next_upstream off

案例分析(nginx proxy_next_upstream导致的一个重复提交错误):
一个请求被重复提交,原因是nginx代理后面挂着2个服务器,请求超时的时候(其实已经处理了),结果nigix发现超时,有把请求转给另外台服务器又做了次处理。

解决办法:

proxy_next_upstream:off

3.2 proxy_next_upstream

语法: proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 |http_404 | off ...;
默认值: proxy_next_upstream error timeout;
上下文: http, server, location

接下来,测试 proxy_next_upstream 是否能够定义失败的标准:

<?php
header(‘RS:Web1‘);
$t = 1;
sleep($t);
echo "sleep {$t}s<br>";
echo "web-1<br>";
?>

web1 - sleep 1秒

<?php
header(‘RS:Web2‘);
header(‘http/1.1 500 Internal Server Error ‘);
#$t = 5;
#sleep($t);
echo "sleep {$t}s<br>";
echo "web-2<br>";
?>

web2 - 返回 500 状态码

nginx配置如下:

upstream 默认后端server失效标准: timeout 和 Connect refuse,在这里例子中,使用

proxy_next_upstream http_500 http_502 http_504
[root@localhost ~]# curl -I -w %{time_total}:%{time_connect}:%{time_starttransfer} http://192.168.118.15/test.php
HTTP/1.1 200 OK
Server: nginx/1.14.2
Date: Thu, 14 Mar 2019 10:53:51 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/5.4.16
RS: Web1

1.006:0.000:1.006

三次都是返回 200 状态,说明 proxy_next_upstream 已经将后端server 返回 500 状态的主机拦截为失效。

3.3 nginx 与后端web连接时间的三个参数

proxy_connect_timeout :后端服务器连接的超时时间_发起握手等候响应超时时间
proxy_read_timeout:连接成功后,等候后端服务器响应时间_其实已经进入后端的排队之中等候处理(也可以说是后端服务器处理请求的时间)
proxy_send_timeout :后端服务器数据回传时间_就是在规定时间之内后端服务器必须传完所有的数据

这里对 proxy_read_timeout 进行测试:

nginx  配置:

<?php
header(‘RS:Web1‘);
$t = 3;
sleep($t);
echo "sleep {$t}s<br>";
echo "web-1<br>";
?>

web1 - test.php - sleep 3

<?php
header(‘RS:Web1‘);
$t = 5;
sleep($t);
echo "sleep {$t}s<br>";
echo "web-1<br>";
?>

web2 - test.php - sleep 5

测试结果:

[root@localhost ~]# curl -I -w %{time_total}:%{time_connect}:%{time_starttransfer} http://192.168.118.15/test.php
HTTP/1.1 504 Gateway Time-out
Server: nginx/1.14.2
Date: Thu, 14 Mar 2019 11:27:59 GMT
Content-Type: text/html
Content-Length: 537
Connection: keep-alive
ETag: "5c89b5df-219"

2.004:0.001:2.004

三次返回结果一致,每次请求均耗时 2秒,这是因为 proxy_read_timeout 设置为 2s ,而后端的程序: web1-sleep 3 、web2-sleep 5,都无法及时响应。

修改 proxy_read_time 为 3 秒,测试如下:

[root@localhost ~]# curl -I -w %{time_total}:%{time_connect}:%{time_starttransfer} http://192.168.118.15/test.php
HTTP/1.1 200 OK
Server: nginx/1.14.2
Date: Thu, 14 Mar 2019 11:33:30 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/5.4.16
RS: Web1

3.004:0.001:3.004

[root@localhost ~]# curl -I -w %{time_total}:%{time_connect}:%{time_starttransfer} http://192.168.118.15/test.php
HTTP/1.1 504 Gateway Time-out
Server: nginx/1.14.2
Date: Thu, 14 Mar 2019 11:33:35 GMT
Content-Type: text/html
Content-Length: 537
Connection: keep-alive
ETag: "5c89b5df-219"

3.005:0.001:3.005

当轮询到 web1 -sleep 3秒时,满足 proxy_read_timeout 返回 200 状态,当轮询到 web2 -sleep 5秒时,超过 proxy_read_timeout 返回 504 状态。

总结:

对于 max_fails 和 fail_timeout 必须连用,但是都不能为 0 ,否则失效检查被禁止,每次都会轮询到失败的节点

proxy_next_upstream 的使用一定要谨慎,有时候程序员会通过 HTTP 状态码来传递信息,如果不小心禁止了会造成不必要的麻烦。

proxy_read_timeout 参数根据业务场景需要进行设定,不宜过长,也不宜过短。

原文地址:https://www.cnblogs.com/hukey/p/10534021.html

时间: 2024-10-02 00:35:25

Nginx - upstream 模块及参数测试的相关文章

nginx upstream模块

参考文档 nginx  upstream模块 http://www.nginx.cn/doc/standard/httpupstream.html #upstream模块: 用于负载均衡 ,反向代理 (proxy fastcgi uwsgi scgi memcached) #语法:  upstream name { ... } upstream static_server { server  A*:80 max_fails=2 fail_timeout=5s; serve    B*:80 ma

nginx upstream模块--负载均衡

Module ngx_http_upstream_module英文文档 upstream模块相关说明1.upstream模块应放于nginx.conf配置的http{}标签内2.upstream模块默认算法是wrr (权重轮询 weighted round-robin) 一.分配方式Nginx的upstream支持5种分配方式,下面将会详细介绍,其中前三种为Nginx原生支持的分配方式,后两种为第三方支持的分配方式. 1.轮询 轮询是upstream的默认分配方式,即每个请求按照时间顺序轮流分配

[转帖]nginx upstream模块--负载均衡

https://www.cnblogs.com/linjiqin/p/5494783.html Module ngx_http_upstream_module英文文档 upstream模块相关说明1.upstream模块应放于nginx.conf配置的http{}标签内2.upstream模块默认算法是wrr (权重轮询 weighted round-robin) 一.分配方式Nginx的upstream支持5种分配方式,下面将会详细介绍,其中前三种为Nginx原生支持的分配方式,后两种为第三方

nginx的upstream模块实现负载均衡

通过nginx搭建负载均衡,这里通过这个upstream模块来实现,在nginx.org的官网可以看到相应的模块 proxy模块也可以实现负载均衡. 第一.打开lamp和lnmp  两个web服务器 Nginx-proxy这台服务器安装nginx,负载均衡需要nginx 安装nginx1.6.2 tar -xf nginx-1.6.2.tar.gz ls cd nginx-1.6.2 useradd -s /sbin/nologin -M nginx ./configure --user=ngi

Nginx专题: upstream模块和缓存的简单使用

Nginx专题: upstream模块和缓存的简单使用 前言: 本文接着上篇Nginx专题: 从编译安装到URL重写来介绍Nginx的负载均衡模块使用方法, 本文的实验没有考虑大多数情况, 例如两个web服务器之间的数据同步等, 主要写Nginx如何作为负载均衡器使用并且缓存 实验拓扑 实验环境 主机 IP地址 功用 lb.anyisalin.com 172.16.1.2 负载均衡并缓存静态资源 web1.anyisalin.com 172.16.1.3 提供web服务 web2.anyisal

nginx的upstream模块

1.upstream 模块介绍: Nginx 的负载均衡功能依赖于ngx_http_upstream_modulemo模块,所支持的方式有 proxy_pass,fastcgi_pass,memcached_pass. 官方地址:http://nginx.org/en/docs/http/ngx_http_upstream_module.html upstream 模块语法: 范例(1): upstream www_real_servers {                #ip_hash; 

nginx的proxy模块及upstream模块介绍

在互联网场景,nginx通常担任处理静态文件的web文件服务器与反向代理服务器的角色. nginx反向代理的特性: 1.在上传文件的场景中,客户端与nginx反向代理建立连接,先把需要上传的文件上传到代理服务器,当代理接收完成文件后,再与上游的真实服务器建立连接,快速把文件上传到服务器(与squid的工作方式不同).为什么要这样做?客户端与代理服务器的连接是互联上慢速连接,而代理与上游服务的连接是内网的高速连接,再因为http的连接是无状态的,客户端与代理的连接可开启keep-alive功能,而

Nginx之upstream模块和proxy模块简单应用

Nginx在web服务中是一个很强大的工具,可以做静态web服务,当然它的最常用的功能就是其负载均衡,下面只是应用nginx的upstream模块和proxy模块来做一个小实验.在此体现的功能也只是冰山一角. upstreem 使用注意:1.只能使用http上下文.2.各server只能直接使用IP或者主机名,不要加协议,在此次实验中使用server IP的方式来代理其后端,其后端使用Apache,提供web服务. 实验拓扑图: 实验配置 本实验主要应用nginx的upstream模块和prox

nginx+upstream+keepalived实现负载均衡

IP地址规划 前端服务器 master 192.168.1.112 slave  192.168.1.113 节点服务器 192.168.1.114 192.168.1.115 1.开启主备服务器的upstream模块 在http模块下添加配置分发节点 upstream aaa.xftz.cn{ server 192.168.1.114; server 192.168.1.115; } upstream bbb.xftz.cn{ server 192.168.1.114; server 192.