首页 > 编程知识 正文

重启后没有nginx,nginx负载均衡原理

时间:2023-05-05 09:12:01 阅读:174797 作者:3255

3359 Zhan.zhi Hu.com/p/127959800

重试机制是为了解决Nginx失败的重试,实现对客户端透明的服务高可用性。 但这部分失败重试机制很复杂,官方文件中没有详细介绍,本文对其进行分析,并结合实际场景实例便于理解。

基本失败重试本节介绍最常见、最基本的失败重试方案。 为了便于理解,使用以下结构进行了分析。 proxy_next_upstream没有特殊的配置。

ustream test { server 127.0.0.133608001 fail _ time out=60s max _ fails=2; # serveraserver 127.0.0.1:8002 fail _ time out=60s max _ fails=2; # Server B}模拟后端异常的方法是直接关闭相应的服务,导致connect refused情况,并应对错误。

在第一个阶段,所有服务都正常,请求以轮询方式依次传输到AB的两台服务器。 如果A节点服务器崩溃,端口无法接通,则会出现这种情况。

1请求转移到a异常,再次转移到b正常处理,A fails 1请求2的b正常处理请求3转移到a异常,再次转移到b正常处理,当A fails 1到达max_fails时,被屏蔽60s屏蔽的a的期间请求全部只被传送给b处理,进行屏蔽

请求1转移到b异常。 此时,所有在线节点异常情况下,AB节点一次恢复,加入生存列表的请求再次转移到a处理异常,再转移到b处理异常,触发no live upstreams错误,返回502错误,所有节点再次恢复,生存列表发生no live upstreams错误并返回502错误的重试限制方法的缺省配置不限制重试机制。 也就是说,尽可能地重试直到失败。 Nginx有两个控制重试次数和重试超时时间的参数:

proxy_next_upstream_tries :设置重试次数。 默认值0表示无限制。 此参数包含对upstream服务器的所有请求次数,包括所有自第一次以来的重试的总和。 proxy_next_upstream_timeout :设置重试最大超时时间。 默认值0表示无限制。 此参数将第一次连接加上后续重试连接时间,不包括连接节点后的处理时间。 为了便于理解,请使用以下结构进行说明(

proxy_connect_timeout 3s; proxy_next_upstream_timeout 6s; proxy_next_upstream_tries 3; ustream test { server 127.0.0.133608001 fail _ time out=60s max _ fails=2; # serveraserver 127.0.0.1:8002 fail _ time out=60s max _ fails=2; # server bserver 127.0.0.1:8003 fail _ time out=60s max _ fails=2; # serverc }第2-3行表示6秒内允许重试3次。 如果超过任何设置,Nginx将退出重试并返回客户端响应。 可能是错误代码。 在iptables DROP中降低对8001、8002端口的请求,模拟了connect timeout的情况。

iptables-I input-ptcp-mtcp-- dport 8001-jdropiptables-I input-ptcp-mtcp-- dport 8002-j drop的具体请求处理如下:

1请求到达Nginx,按照以下逻辑首先转移到a处理,3s后连接超时,A fails 1重试进行b处理,3s后连接超时,B fails 1到达设定的6s重试超时,直接进行` 504 gates 不返回重试客户端(c请求2 ) c正常处理请求3 )到达Nginx先转移到b处理,3s后连接超时,b )到达max_fails被屏蔽,60s后转移到c正常处理请求4 ) 60s转移到c,所有后续请求转移到c,在AB掩码过期后,重新加入服务器生存列表。 通过以上示例可知,proxy_next_upstream_timeout设定项目对重试机制的限制、重试次数的情况也是如此。 这里省略详细的说明。

下面将分别介绍通过backup服务器Nginx支持设置备用节点的过程,因为在所有联机节点出现异常的情况下,备用节点将启用备用节点,同时备用节点也会影响失败的重试逻辑。 在upstream配置中,可以在backup命令中定义备用服务。 其含义如下。

通常,不会将请求转发给

到 backup 服务器,包括失败重试的场景当所有正常节点全部不可用时,backup 服务器生效,开始处理请求一旦有正常节点恢复,就使用已经恢复的正常节点backup 服务器生效期间,不会存在所有正常节点一次性恢复的逻辑如果全部 backup 服务器也异常,则会将所有节点一次性恢复,加入存活列表如果全部节点(包括 backup)都异常了,则 Nginx 返回 502 错误

为了方便理解,使用了以下配置进行说明:

upstream test { server 127.0.0.1:8001 fail_timeout=60s max_fails=2; # Server A server 127.0.0.1:8002 fail_timeout=60s max_fails=2; # Server B server 127.0.0.1:8003 backup; # Server C}

在最初始阶段,所有服务器都正常,请求会按照轮询方式依次转发给 AB 两个节点处理。当只有 A 异常的情况下,与上文没有 backup 服务器场景处理方式一致,这里就不重复介绍了。

假设在 A 的屏蔽期还没结束时,B 节点的服务也崩溃,端口不通,则会出现:

请求 1 转到 B 处理,异常,此时所有线上节点异常,会出现:AB 节点一次性恢复,都重新加入存活列表请求转到 A 处理异常,再重试到 B 处理异常,两者 fails 都 +1因 AB 都异常,启用 backup 节点正常处理,并且 AB 节点一次性恢复,加入存活列表请求 2 再依次经过 A、B 节点异常,转到 backup 处理,两者 fails 都达到 max_fails:AB 节点都将会被屏蔽 60s,并且不会一次性恢复backup 节点正式生效,接下来所有请求直接转到 backup 处理直到 AB 节点的屏蔽到期后,重新加入存活列表

假设 AB 的屏蔽期都还没结束时,C 节点的服务也崩溃,端口不通,则会出现

请求 1 转到 C 异常,此时所有节点(包括 backup)都异常,会出现:ABC 三个节点一次性恢复,加入存活列表请求转到 A 处理异常,重试到 B 处理异常,最后重试到 C 处理异常触发 `no live upstreams` 报错,返回 502 错误所有节点再次一次性恢复,加入存活列表请求 2 依次经过 AB 节点异常,重试到 C 异常,最终结果如上个步骤,返回 502 错误踩坑集锦

如果不熟悉 HTTP 协议,以及 Nginx 的重试机制,很可能在使用过程中踩了各种各样的坑:

部分上游服务器出现异常却没有重试一些订单创建接口,客户端只发了一次请求,后台却创建了多个订单,等等…

以下整理了一些常见的坑,以及应对策略。

需要重试却没有生效 接口的 POST 请求允许重试,但实际使用中却没有出现重试,直接报错。

从 1.9.13 版本,Nginx 不再会对一个非幂等的请求进行重试。如有需要,必须在 proxy_next_upstream 配置项中显式指定 non_idempotent 配置。参考 RFC-2616 的定义:

幂等 HTTP 方法:GET、HEAD、PUT、DELETE、OPTIONS、TRACE非幂等 HTTP 方法:POST、LOCK、PATCH

如需要允许非幂等请求重试,配置参考如下(追加 non_idemponent 参数项):

proxy_next_upstream error timeout non_idemponent;

该配置需要注意的点:

添加非幂等请求重试是追加参数值,不要把原来默认的 error/timeout 参数值去掉必须明确自己的业务允许非幂等请求重试以避免业务异常禁止重试的场景 一些场景不希望请求在多个上游进行重试,即使上游服务器完全挂掉。

正常情况下,Nginx 会对 error、timeout 的失败进行重试,对应默认配置如下:

proxy_next_upstream error timeout;

如希望完全禁止重试,需要显式指定配置来关闭重试机制,配置如下:

proxy_next_upstream off; 重试导致性能问题 错误配置了重试参数导致 Nginx 代理性能出现异常

默认的 error/timeout 是不会出现这种问题的。在定义重试场景时,需要结合业务情况来确定是否启用自定义错误重试,而不是单纯去复制其他服务的配置。比如对于某个业务,没有明确自己业务情况,去网上复制了 Nginx 配置,其中包括了:

proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;

那么只需要随便定义一个不存在的 URI 去访问该服务频繁去请求该服务,就可以重复触发 Nginx no live upstreams 报错,这在业务多情的西牛情况下,性能将受到极大影响。同样,如果使用的代码框架存在不标准 HTTP 处理响应情况,恶意构造的请求同样也会造成类似效果。

因此在配置重试机制时,必须先对业务的实际情况进行分析,严谨选择重试场景。

异常的响应超时重试 某幂等接口处理请求耗时较长,出现非预期的重试导致一个请求被多次响应处理。

假设该接口处理请求平均需要 30s,而对应的代理超时为:

proxy_read_timeout 30s;

默认的重试包含了 timeout 场景,在这个场景下,可能会有不到一半的请求出现超时情况,同时又因为是幂等请求,所有会进行重试,最终导致一个的超时请求会被发到所有节点处理的请求放大情况。

因此在进行超时设置时,也必须要跟进业务实际情况来调整。可以适当调大超时设置,并收集请求相关耗时情况进行统计分析来确定合理的超时时间。

异常的连接超时重试 因上游服务器异常导致连接问题,客户端无超时机制,导致请求耗时非常久之后才失败。

已知所有上游服务器异常,无法连接或需要非常久(超过 10s)才能连接上,假设配置了连接超时为:

proxy_connect_timeout 10;

在这种情况下,因客户端无超时设置,幂等请求将卡住 10*n 秒后超时(n 为上游服务器数量)。因此建议:

客户端设置请求超时时间配置合理的 proxy_connect_timeout配合 proxy_next_upstream_timeout、proxy_next_upstream_tries 来避免重试导致更长超时

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。