记录一次nginx重试机制的踩坑(一般出现不了)

简介: 记录一次nginx重试机制的踩坑

一、问题的产生

最近这几天公司的一个线上的系统出现了故障,操作人员导入了一份excel后,由于处理时间比较长,前端界面一直显示在loading,等到最后就报“接口不可用“了,然后后台的开发人员去查询数据库,发现生成了多条的导入处理任务,这时候,后台、前端、运维人员开始争吵了,各说不是我的问题,最后问题推给了“中间件”。

image.png

二、分析问题

1、 系统现状

既然要分析问题,那先要了解这个系统的部署及网络的情况,从用户操作到服务器的过程。来看下这个系统的部署图,这个图是主要的部分,次要的部分就没画出来了。大致情况就是,用户在网页上操作,数据通过网络传递回服务端,这个过程使用了CDN,然后到负载器,在分发到nginx,nginx在分发到后端的服务上,在到数据库。

image.png

另外,这是一个前后端分离的项目,前端采用Vue开发,后台采用java开发,数据库用mysql。

2、 排查问题

后台写入数据重复,后端的开发一想就是前端重复提交的问题,找前端的同事看,前端说我没有问题呀,操作上还加了loading,用户不可能点第二次,后端开发还是不信,那就打开F12吧,我靠,没有重复的网络请求。

image.png

后端开发找到运维人员,运维说服务器我没动过呀,还是原来那样子。一堆人讨论了半天,有的说是CDN,有的说是nginx,各有各的说法。

3、问题超乎想象

看大家都没有头绪,我说来看下nginx的access log吧,通过简单的grep命令,找到接口对应的请求记录,MD,一看吓一跳,一个接口处理要60s?
image.png

找到对应的开发人员询问情况,它说后台处理确实是要超60s的,在问下前端超时是多久,前端说是30s,这里只能说“我服了”。 正常情况下,前端操作的超时要大于后端的超时,不然后端处理完了,就无法返回给到前端了,前端都超时了,用户可能另起操作或者关闭了。(PS:这种任务就应该做成异步,不知当初是怎么设计的)。
在仔细地看下access log,发现同个接口请求之间间隔的时间是差不多的,不像是前端用户手动操作导致,那会是什么问题?
image.png
image.png

脑海里闪现了是不是nginx的重次机制导致的呢,于是打开这个系统对应的location的conf文件,发现这个API对应的location中并未作个性化配置,都是默认配置。隐约记得location中有几个超时的配置项目,用于控制与后端的连接,读取,发送的。

三、解决问题

1、 nginx的超时、重试机制

找到nginx中用于配置location的超时的配置项,一共有三个:

  • proxy_connect_timeout time:与后端/上游服务器建立连接的超时时间,默认为60s。
  • proxy_read_timeout time:设置从后端/上游服务器读取响应的超时时间,默认60s。此超时时间指的是2次成功读操作时间间隔,而不是读取整个响应体的超时时间。如果超时时间内没有任何响应,则Nginx将关闭连接。
  • proxy_send_timeout time:设置往后端/上游服务器发送请求的超时时间,默认60s。此超时时间指的是2次成功读操作时间间隔,而不是读取整个响应体的超时时间。如果超时时间内没有任何响应,则Nginx将关闭连接。

失败重试机制设置

  • proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | non_idempotent | off ... :配置什么情况下需要向上游服务器进行重试。默认为:error timeout。error表示读写出错;timeout表示超时;invalid_header表示头信息有误;non_idempotent表示RFC-2616定义的非幂等HTTP方法(POST、LOCK、PATCH),也可以在失败后重试(默认幂等方法GET、HEAD、PUT、DELETE、OPTIONS、TRACE);off表示禁用重试。
  • proxy_next_upstream_tries number:设置重试次数,默认0表示不限制。这里的次数包含第一次请求。
  • proxy_next_upstream_timeout time:设置重试最大超时时间,默认0表示不限制。

上面2个值的关系是且的关系,在限制时间内或者重试次数达到一个值就会结束重试,并返回客户端响应。

2、 结合现状分析

从官方的文档中发现:指令 proxy_connect_timeout 或 proxy_read_timeout 为超时状态时,都会触发 proxy_next_upstream 的 timeout 条件,当条件成立时,就会执行proxy_next_upstream_tries中配置的重试次数。

再来看下当前的nginx,location中都是默认值,而后端服务的处理时长却超过60s,这里已经达到触发proxy_next_upstream的条件,请求自动进入重试,从而导致后端服务处理了多次请求,写入了重复的记录。

3、 解决当前问题

既然已经确定问题,那调整相关的参数,在location中加入上面的几个参数,并调整下时长,如下示例。

location /xxx {
   
   
 proxy_connect_timeout 5s;
 proxy_read_timeout 100s;
 proxy_send_timeout 70s;
 proxy_next_upstream error timeout;
 proxy_next_upstream_timeout 70;
 proxy_next_upstream_tries 1;
 proxy_pass http://backend_server;
 add_header upstream_addr $upstream_addr;
 }

重新reload下nginx的配置,让用户在重新操作一次,虽然界面还是在loading,但观察数据库中的记录,已经没有重复写入了,并且前端响应也变快了。

至些问题解决。

四、总结

虽然解决了问题,但好像高兴不起来,MD,处理要超过60s,这是什么概念,要求开发排查到底是那里慢。如果确实是要这么久,要做成异步来处理,不能这样一直loading,体验不好。
image.png

另外,这是通过中间件来解决重复的问题,其实这个说白了,是接口幂等性的问题,应该采用幂等性的处理规则来解决。比如在前端的请求加上一个唯一标识,后台通过对标识的加锁,或者数据库唯一主键、或者文件的MD5码等来解决。

目录
相关文章
|
负载均衡 应用服务中间件 nginx
Nginx之upstream被动式重试机制解读z
Nginx之upstream被动式重试机制解读z
|
弹性计算 负载均衡 应用服务中间件
Nginx重试机制,浏览器重复请求两次多次
问题找到了,原因是Nginx配置文件中,超时时间太短了:proxy_connect_timeout 20;;在Nginx的默认配置是:在客户端请求服务器超时的情况下,Nginx会自动转发该请求到另外一台服务器上,这是Nginx的一种容错机制,所以Nginx的访问日志中会出现同一条请求而两台服务器都执行了一遍的情况,这样以来,程序如果没有做幂等性操作的话数据库会出现两条记录。
1603 0
|
1月前
|
编解码 应用服务中间件 Linux
centos配置nginx-rtmp实现ffmpeg转码rtsp为rtmp视频流
centos配置nginx-rtmp实现ffmpeg转码rtsp为rtmp视频流
171 1
|
5月前
|
应用服务中间件 Linux 网络安全
Centos 8.0中Nginx配置文件和https正书添加配置
这是一份Nginx配置文件,包含HTTP与HTTPS服务设置。主要功能如下:1) 将HTTP(80端口)请求重定向至HTTPS(443端口),增强安全性;2) 配置SSL证书,支持TLSv1.1至TLSv1.3协议;3) 使用uWSGI与后端应用通信(如Django);4) 静态文件托管路径设为`/root/code/static/`;5) 定制错误页面(404、50x)。适用于Web应用部署场景。
660 87
|
5月前
|
负载均衡 应用服务中间件 nginx
Nginx配置与命令
Nginx 是一款高性能的 HTTP 和反向代理服务器,其配置文件灵活且功能强大。本文介绍了 Nginx 配置的基础结构和常用指令,包括全局块、Events 块、HTTP 块及 Server 块的配置方法,以及静态资源服务、反向代理、负载均衡、HTTPS 和 URL 重写等功能实现。此外,还提供了常用的 Nginx 命令操作,如启动、停止、重载配置和日志管理等,帮助用户高效管理和优化服务器性能。
|
1月前
|
Ubuntu 安全 应用服务中间件
详细指南:配置Nginx服务器在Ubuntu平台上
以上步骤涵盖了基本流程:从软件包管理器获取 Ngnix, 设置系统服务, 调整UFW规则, 创建并激活服务器块(也称作虚拟主机), 并进行了初步优化与加固措施。这些操作都是建立在命令行界面上,并假设用户具有必要权限(通常是root用户)来执行这些命令。每个操作都有其特定原因:例如,设置开机启动确保了即使重启后也能自动运行 Ngnix;而编辑server block则定义了如何处理进入特定域名请求等等。
198 18
|
1月前
|
Ubuntu 安全 应用服务中间件
详细指南:配置Nginx服务器在Ubuntu平台上
以上步骤涵盖了基本流程:从软件包管理器获取 Ngnix, 设置系统服务, 调整UFW规则, 创建并激活服务器块(也称作虚拟主机), 并进行了初步优化与加固措施。这些操作都是建立在命令行界面上,并假设用户具有必要权限(通常是root用户)来执行这些命令。每个操作都有其特定原因:例如,设置开机启动确保了即使重启后也能自动运行 Ngnix;而编辑server block则定义了如何处理进入特定域名请求等等。
207 17
|
2月前
|
数据建模 应用服务中间件 PHP
配置nginx容器和php容器协同工作成功,使用ip加端口的方式进行通信
本示例演示如何通过Docker挂载同一宿主目录至Nginx与PHP容器,实现PHP项目运行环境配置。需注意PHP容器中监听地址修改为0.0.0.0:9000,并调整Nginx配置中fastcgi_pass指向正确的IP与端口。同时确保Nginx容器中/var/www/html权限正确,以避免访问问题。
配置nginx容器和php容器协同工作成功,使用ip加端口的方式进行通信
|
3月前
|
应用服务中间件 网络安全 nginx
配置Nginx以支持Websocket连接的方法。
通过上述配置,Nginx将能够理解WebSocket协议的特殊要求,代理Websocket流量到合适的后端服务器。注意,Websocket并不是HTTP,尽管它最初是通过HTTP请求启动的连接升级,因此保证Nginx了解并能够妥善处理这种升级流程是关键。
700 10
|
2月前
|
Ubuntu 应用服务中间件 Linux
在Ubuntu上配置Nginx实现开机自启功能
至此,Nginx应该已经被正确地设置为开机自启。在Ubuntu中利用 `systemd`对服务进行管理是一种高效的方式,为系统管理员提供了强大的服务管理能力,包括但不限于启动、停止、重启服务,以及配置服务的开机自启动。通过这些简洁的命令,即使是对Linux不太熟悉的用户也能轻松地进行配置。
127 0