[转帖]nginx的重试机制 proxy_next_upstream

nginx,重试,机制,proxy,next,upstream · 浏览次数 : 0

小编点评

**Nginx反向代理中的错误重试机制** Nginx通过反向代理做负载均衡时,如果被代理的其中一个服务发生错误或者超时的时候,通常会自动重试其他的服务,从而实现服务的高可用性。 **错误重试机制的配置** 可以使用`proxy_next_upstream`选项来指定在什么情况下Nginx会将请求转移到其他服务器上。其默认值是`error timeout`,即发生网络错误以及超时,才会重试其他服务器。默认情况下服务返回500状态码是不会重试的,如果想在响应500状态码时也进行重试,可以配置`proxy_next_upstream error timeout http_500`。 **示例配置** ```nginx upstream nginxretry { server 127.0.0.1:9030 weight=10; server 127.0.0.1:9031 weight=10; } server { listen 9039; location / { proxy_pass http://nginxretry; proxy_next_upstream error timeout http_500; } } ``` **其他配置项** 除了`proxy_next_upstream`之外,还有其他配置项可以用于控制错误重试,包括: * `proxy_set_header`用于设置在请求中传递的信息,例如错误码。 * `proxy_redirect`用于重定向请求。 * `proxy_read_timeout`和`proxy_connect_timeout`用于设置连接和读写超时时间。

正文

https://blog.csdn.net/xiao__gui/article/details/89441162

https://zhuanlan.zhihu.com/p/35803906

https://www.cnblogs.com/powerwu/articles/9791295.html

https://pandaychen.github.io/2019/12/15/NGINX-SMOOTH-WEIGHT-ROUNDROBIN-ANALYSIS/

 

Nginx通过反向代理做负载均衡时,如果被代理的其中一个服务发生错误或者超时的时候,通常希望Nginx自动重试其他的服务,从而实现服务的高可用性。实际上Nginx本身默认会有错误重试机制,并且可以通过proxy_next_upstream来自定义配置。

如果不了解HTTP协议以及Nginx的机制,就可能在使用过程中遇到各种各样的坑。例如服务出现了错误或超时却未重试,或者一些例如创建订单或发送短信这类的HTTP接口,客户端只发送一次请求,后台却由于Nginx重试导致创建了多个订单,或者收到多条短信,导致一些业务上的问题。

在Nginx配置文件中,proxy_next_upstream用于指定在什么情况下Nginx会将请求转移到其他服务器上。其默认值是proxy_next_upstream error timeout,即发生网络错误以及超时,才会重试其他服务器。默认情况下服务返回500状态码是不会重试的,如果想在响应500状态码时也进行重试,可以配置:
 

proxy_next_upstream error timeout http_500;

当然还有http_502http_503http_404等可以指定在出现哪些状态码的情况下需要重试。具体配置项可以参考官方文档: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream 。 

  1. upstream nginxretry {
  2. server 127.0.0.1:9030 weight=10;
  3. server 127.0.0.1:9031 weight=10;
  4. }
  5. server {
  6. listen 9039;
  7. location / {
  8. proxy_pass http://nginxretry;
  9. proxy_next_upstream error timeout http_500;
  10. }
  11. }

配置完成后重启Nginx,使用GET方式请求 http://localhost:9039/ ,再分别查看9030和9031两个端口号对应的服务日志,可以发现两个服务都收到请求,也就是Nginx在访问其中一个服务收到500错误状态码后,又尝试去访问另一个服务。

再次使用POST方式请求 http://localhost:9039/ ,再分别查看9030和9031两个端口号对应的服务日志,可以发现只有一个服务收到请求。也就是当请求类型是POST时,Nginx默认不会失败重试。如果想让POST请求也会失败重试,可以继续向下阅读。

non_idempotent

Nginx文档中可以看到proxy_next_upstream有一个选项non_idempotent:

normally, requests with a non-idempotent method (POST, LOCK, PATCH) are not passed to the next server if a request has been sent to an upstream server (1.9.13); enabling this option explicitly allows retrying such requests;

通常情况下,如果请求使用非等幂方法(POST、LOCK、PATCH),请求失败后不会再到其他服务器进行重试。加上non_idempotent选项后,即使是非幂等请求类型(例如POST请求),发生错误后也会重试。

如果想让POST请求也会失败重试,需要配置non_idempotent

  1. upstream nginxretry {
  2. server 127.0.0.1:9030 weight=10;
  3. server 127.0.0.1:9031 weight=10;
  4. }
  5. server {
  6. listen 9039;
  7. location / {
  8. proxy_pass http://nginxretry;
  9. proxy_next_upstream error timeout http_500 non_idempotent;;
  10. }
  11. }

重启Nginx后再次使用POST请求访问 http://localhost:9039/ ,再分别查看9030和9031两个端口号对应的服务日志,可以看到两个服务都收到请求,也就是POST请求也会重试了。不过实际上在生产环境中,不建议加上non_idempotent选项,具体原因可以继续往下阅读。

什么是幂等方法

HTTP协议规范中,对幂等方法(Idempotent Method)做了以下定义:

A request method is considered “idempotent” if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request.

如果使用该方法的多个相同请求对服务器的预期效果与单个请求的效果相同,则认为请求方法是幂等的。常见的HTTP请求方法中,GET是幂等的,而POST是非幂等的。如果在回答面试题"GET和POST区别"时能答出这一点,才能说明对HTTP协议有一定的理解。

在做业务开发是如何理解幂等性,举个最简单的例子:GET方法一般用于获取数据,如果获取的是数据库数据,对应的是SELECT语句。同样的SELECT语句执行一次还是多次,都不会影响数据。而POST一般对应INSERT,如果执行多次后,可能会造成数据重复插入的问题。所以不要使用GET方法做一些INSERT操作,在业务开发时要遵循HTTP协议规范。

生产环境中为什么不建议加上non_idempotent选项?因为无论是发生500错误还是timeout,服务器上的业务可能都已经执行过了,而重试会导致非幂等方法重复执行,从而导致业务问题,例如一个请求会创建了多个订单,或者收到多条短信的问题。

与[转帖]nginx的重试机制 proxy_next_upstream相似的内容:

[转帖]nginx的重试机制 proxy_next_upstream

https://blog.csdn.net/xiao__gui/article/details/89441162 https://zhuanlan.zhihu.com/p/35803906 https://www.cnblogs.com/powerwu/articles/9791295.html h

[转帖]nginx的重试机制 proxy_next_upstream

https://blog.csdn.net/xiao__gui/article/details/89441162 https://zhuanlan.zhihu.com/p/35803906 https://www.cnblogs.com/powerwu/articles/9791295.html h

[转帖]nginx的proxy_next_upstream使用中的一个坑

https://zhuanlan.zhihu.com/p/35803906 今天线上系统出了点问题,机房的电信出口突然不通了,原本以为能自动切换的nginx配置,居然没有生效,导致了业务告警,手工紧急处理了才解决了。 当时的设想是,如果这个服务的访问,出现了500或者超时的情况,会自动重试到下一个服

[转帖]nginx http超时重试幂等问题

https://blog.csdn.net/wangtingting_100/article/details/89842557 nginx做反向代理时,作为负载均衡器,对执行失败的任务默认会调度到其他节点执行。 默认设置:proxy_next_upstream error timeout #发生网络

【转帖】nginx变量使用方法详解-5

https://www.diewufeiyang.com/post/579.html 前面在 (二) 中我们已经了解到变量值容器的生命期是与请求绑定的,但是我当时有意避开了“请求”的正式定义。大家应当一直默认这里的“请求”都是指客户端发起的 HTTP 请求。其实在 Nginx 世界里有两种类型的“请

[转帖]acme 中文说明

https://github.com/acmesh-official/acme.sh/wiki/%E8%AF%B4%E6%98%8E acme.sh 实现了 acme 协议, 可以从 letsencrypt 生成免费的证书. 主要步骤: 安装 acme.sh 生成证书 copy 证书到 nginx/

[转帖]Kubernetes 领进门 | 使用 Ingress-nginx 反向代理外部站点

https://cloud.tencent.com/developer/article/2187041 warning: 这篇文章距离上次修改已过204天,其中的内容可能已经有所变动。 本文旨在展示如何使用 ingress-nginx 作为反向代理加速集群外部服务原理。下文以反向代理 github

[转帖]nginx的map指令

一 ngx_http_map_module模块 1) map 指令是由 'ngx_http_map_module 模块'提供的,默认情况下安装 nginx 都会'安装'该模块. 2) map 的主要作用是'创建自定义变量',通过使用 nginx 的'内置'变量,去'匹配'某些特定规则;如果匹配成功则

[转帖]nginx的ip_hash算法

概念 根据用户请求的ip,利用算法映射成hash值,分配到特定的tomcat服务器中。主要是为了实现负载均衡,只要用户ip固定,则hash值固定,特定用户只能访问特定服务器,解决了session的问题。 源码分析 ip_hash算法的处理代码位于src\http\modules\ngx_http_u

[转帖]nginx的Mainline version、Stable version、Legacy version的版本区别

https://blog.csdn.net/zwjzwj520520/article/details/62883317 Nginx官网提供了三个类型的版本Mainline version:Mainline 是 Nginx 目前主力在做的版本,可以说是开发版Stable version:最新稳定版,生