问题排查:nginx能跑,但是只能跑一会,不能跑多了

问题,排查,nginx,但是,只能,一会,不能 · 浏览次数 : 2431

小编点评

# df卡死的原因分析 df卡死的原因主要有以下几个原因: 1. **nfs服务端关闭了**: 由于您关闭了nfs服务器,客户端无法获取到nfs server上的文件系统信息。 2. **nfs连接超时**: 由于您设置了过高的timeo值,客户端在等待nfs server上线时超时。 3. **nfs服务端资源不足**: 由于您设置了过高的retrans值,服务器在处理客户端请求时资源不足。 4. **nfs服务器内存不足**: 由于您设置了过高的wsize值,服务器在处理客户端请求时内存不足。 5. **nfs连接错误**: 由于您设置了过高的hard模式,客户端在等待nfs server上线时出现连接错误。 # 解决方案 1. **重新启动nfs服务器**: 启动nfs服务器,确保它正常运行。 2. **设置时间o值**: 降低timeo值,使客户端在等待nfs server上线时更有效地等待。 3. **设置retrans值**: 降低retrans值,降低服务器在处理客户端请求时等待的超时时间。 4. **设置wsize值**: 降低wsize值,降低服务器在处理客户端请求时处理的请求数量。 5. **设置hard模式**: 降低hard值,让客户端在等待nfs server上线时更有效地处理连接错误。 # 总结 df卡死的原因主要有以下几个原因: 1. nfs服务端关闭了 2. nfs连接超时 3. nfs服务端资源不足 4. nfs服务器内存不足 5. nfs连接错误

正文

背景

上周都是查测试环境的问题,比如,我上一篇写的问题排查:nginx的反向代理感觉失效了一样 ,就是说这个事的。在文章里,最终查到是nginx的全连接队列满了(每个监听端口有个队列,完成三次握手的请求会进入这个监听端口的全连接队列,队列大小是只有128,比较小),我当时的解决方式,是把队列大小调大到了512,然后重启nginx,果然功能正常了。

但当时没有去再多问一个为什么:为什么nginx的全连接队列会满呢?而且这个功能虽然用得少,但是之前应该都好好的,突然就抽风了?

nginx的全连接队列,简单,它就是一个队列,网络协议栈负责将完成三次握手的连接放到该队列,算是生产者;那么,消费者是谁呢,自然是我们的应用程序,应用程序每次调用accept的时候,就会从队列中获取一个连接,获取了之后,队列也就空出来了。

我翻了下accept这个syscall的手册(man accept),https://linux.die.net/man/2/accept:

It extracts the first connection request on the queue of pending connections for the listening socket, sockfd, creates a new connected socket, and returns a new file descriptor referring to that socket.

这块是说,是从队列头部获取,先进先出;获取到了之后,给调用方返回一个文件描述符,指向该socket。

If no pending connections are present on the queue, and the socket is not marked as nonblocking, accept() blocks the caller until a connection is present. If the socket is marked nonblocking and no pending connections are present on the queue, accept() fails with the error EAGAIN or EWOULDBLOCK.

In order to be notified of incoming connections on a socket, you can use select(2) or poll(2). A readable event will be delivered when a new connection is attempted and you may then call accept() to get a socket for that connection. Alternatively, you can set the socket to deliver SIGIO when activity occurs on a socket; see socket(7) for details.

这里又提到,如果队列里没有连接,且该监听socket不是非阻塞的,那么accpet调用会阻塞;如果socket是非阻塞的,那么此时就会返回错误:EAGAIN or EWOULDBLOCK。

为了在新的连接到达时(进入队列时)能够得到提醒,我们可以使用select或者poll机制。当新连接到达时,会有一个可读事件发送给程序,此时再去调用accept就肯定能获取到连接,而不会阻塞。

我发现,文档写得还是非常清楚,很有价值,总的来说,应用程序就是那个消费者,队列会满,那肯定是消费者有问题,消费者是nginx,nginx能有啥问题呢,还真不知道,我当时以为猜测可能是请求处理有点慢吧,我把队列给你加大了,应该就没事了。

当天下午有事,也没管了,结果第二天,测试同事说,又不行了,我去看了下队列(ss -lnt|grep 8088),512的队列,又满了。

排查

nginx 日志

说实话,当时真的有点无语,因为手里还有别的事,也不想一直耗在这个事情上,但是,我们也不能阻碍测试同事工作开展,这也是份内事。

因为当时这个nginx,除了监听了我们关注的8088端口,还监听了8082 8080等端口,我以为是被其他端口影响到了,也看了下这两个端口的队列长度,ss -lnt|grep 8082,发现队列长度是0,只有我们8088端口是满的。

我当时想过,怎么看看这些队列里都是啥内容,但感觉意义不大,无非就是那些socket,所以没有深入去看。

然后又去看nginx日志,首先奇怪的一点是,我是周四的下午2点多处理完队列长度,重启nginx,然后access日志也只打到了2点20分左右就没了,error日志也是。

另外,error日志倒是打印了一些内容,就是有很多获取图片的请求,处理失败了,就是说open xxx.jpg failed之类的,我当时想着估计是图片找不到吧,404啥的,这种见多了,一般也不怎么理。

我还是去看了下那个文件,结果,ssh卡死了:

[root@168assi log]# ll /hxspace/production/files/unsafty/hxtg_dd
^C^C^C^C

我之前就是感觉这个机器有点问题,经常各种命令都卡死,现在ll都不行了。。

常规检查

然后就是开始检查系统资源,首先是top,按cpu排序和按内存排序,都没发现很离谱的占用很高的应用。

但是,top中看到1、5/15分钟的平均负载基本在12左右,我们是8核,按我理解,12/8=1.5,那基本上,每个核上有1个线程在运行,还有0.5个线程在等待运行。

感觉是有点高,但我不太擅长排查cpu问题,也没有再深入。

然后free -h检查了下内存,空闲内存也还很多,8个g,感觉没问题。

然后是磁盘,df一执行,结果直接卡死了,也不知道咋回事,之前就是感觉这机器有问题,之前lsof命令也是执行卡死。

当时都怀疑是不是磁盘有问题,还是机器哪里有问题,要不要换台机器部署算了。

内核日志

再检查下内核日志吧,dmesg -T,浏览了下。没看到nginx的相关日志。但是看到一些乱七八糟的内容:

[五 8月 25 11:06:58 2023] nfs: server 10.0.251.111 not responding, timed out
[五 8月 25 11:06:58 2023] nfs: server 10.0.251.111 not responding, timed out
[五 8月 25 11:12:04 2023] nfs: server 10.0.251.111 not responding, still trying

然后又去看了/var/log/messages,也没啥特别的。

strace查看df阻塞点

之前不是执行df,把我ssh卡死了嘛,我这次想看看到底是哪里卡住了,于是用strace跟踪了下。

[root@168assi servers]# strace -q -f -s 500 df

结果,这个命令卡在了下面这个地方:

stat("/run/user/42", {st_mode=S_IFDIR|0700, st_size=180, ...}) = 0
stat("/sys/fs/fuse/connections", {st_mode=S_IFDIR|0755, st_size=0, ...}) = 0
stat("/run/user/42/gvfs", 0x7ffe818bf1a0) = -1 EACCES (Permission denied)
stat("/run/user/0", {st_mode=S_IFDIR|0700, st_size=40, ...}) = 0
stat("/hxspace/production/files/unsafty/hxtg_dd", ^C^C^C^C

可以看到我狂按ctrl c吗,就是因为卡死了

检查挂载

这个目录有问题啊,因为这个目录我还是很有印象的,nginx读图片就是在这个目录下读,然后还失败了。

然后我想起来那个内核日志里nfs报错的相关信息,我他么感觉,这个目录是不是网络存储啊,就是挂载到了nfs server。

然后我执行mount -l看了下,果然找到了nfs的踪迹:

...
10.0.251.111:/home/app on /hxspace/production/files/unsafty/hxtg_dd type nfs4 (rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=10.0.251.192,local_lock=none,addr=10.0.251.111)

这个挂载也就是说,/hxspace/production/files/unsafty/hxtg_dd挂载的是nfs服务器10.0.251.111的/home/app目录.

然后,我ping了下这个机器,不通。此时,基本确定就是这个问题了。

解决

所以,我猜测,df、lsof等各种要遍历文件夹的命令都卡死了,那估计nginx去读取那个目录下的文件,也卡死了,worker如果卡死,那么nginx负责accept的进程,应该就会停止去accept连接,进而导致全连接队列满。

但是,怎么验证是这个问题呢?

我们把nginx.conf中读取那个目录的配置先删了,然后再试,果然,这次全连接队列再没有积压了,肉眼看到的一直都是0.

但是,把别人配置删了也不合适,那看看能不能恢复nfs吧?

我们先去找服务器管理的同事,结果跟我们说,这个nfs服务器已经被回收了,果然,主打一个混乱。

行吧,反正是测试环境,既然nfs服务器没了,我们也没打算再搭一个,后边问到相关业务同事,已经没在用这台机器了,那就不用顾忌他们了,那这个挂载就得想办法去掉,不然各种命令都卡死,实在不爽。

去掉mount挂载,采用的umount命令,结果执行失败,提示device is busy。

后边查网上文章,需要ps aux找出状态为D的(也就是TASK_UNINTERRUPTIBLE,是一种不可中断的状态),我发现查出来的基本就是我之前卡死的那些df等命令。

kill 9强杀这些进程后,再去执行取消挂载,成功了:

[root@168assi ~]# umount -f -v 10.0.251.111:/home/app
/hxspace/production/files/unsafty/hxtg_dd: nfs4 mount point detected
/hxspace/production/files/unsafty/hxtg_dd: umounted

扩展:nfs

我们这里作为nfs客户端,挂载时,其实是可以指定选项的,其中有个选项如下:

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/deployment_guide/s1-nfs-client-config-options

hard or soft — Specifies whether the program using a file via an NFS connection should stop and wait (hard) for the server to come back online, if the host serving the exported file system is unavailable, or if it should report an error (soft).

If hard is specified, the user cannot terminate the process waiting for the NFS communication to resume unless the intr option is also specified.

If soft is specified, the user can set an additional timeo= option, where specifies the number of seconds to pass before the error is reported.

也就是可以指定hard或soft,hard就是nfs服务端如果像我们这种情况,直接ip都不通了,客户端会一直死等,直到nfs server上线;而soft就是会超时,然后报错。

我们这边,这次就是挂载用了hard模式,不知道怎么考虑的。

10.0.251.111:/home//app on /hxspace/production/files/unsafty/hxtg_dd type nfs4 (rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=10.0.251.192,local_lock=none,addr=10.0.251.111)

总结

这次遇到的这个问题,说白了,最终就是因为关闭了nfs服务器的问题,也就能解释,为啥以前没问题了。

另外,我在写本篇的时候,感觉几年前好像研究过全连接队列的问题,去找了下之前文章,发现现象竟然是一模一样,几年下来忘得好干净,果然是唯手熟尔:

https://www.cnblogs.com/grey-wolf/p/10999342.html

image-20230826161022861

参考文章

https://www.cnblogs.com/yuboyue/archive/2011/07/18/2109867.html

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/deployment_guide/s1-nfs-client-config-options

https://superuser.com/questions/1562153/shutdown-of-rhel-6-9-7-7-nfs-client-hangs-when-nfs-server-has-become-unavailab

https://unix.stackexchange.com/questions/328746/how-can-i-monitor-the-length-of-the-accept-queue (查看accept队列内容)

https://krisnova.net/posts/linux-accept-queues/

与问题排查:nginx能跑,但是只能跑一会,不能跑多了相似的内容:

问题排查:nginx能跑,但是只能跑一会,不能跑多了

# 背景 上周都是查测试环境的问题,比如,我上一篇写的[问题排查:nginx的反向代理感觉失效了一样 ](https://www.cnblogs.com/grey-wolf/p/17655238.html),就是说这个事的。在文章里,最终查到是nginx的全连接队列满了(每个监听端口有个队列,完成三

问题排查:nginx的反向代理感觉失效了一样

# 背景 最近,负责基础设施的同事,要对一批测试环境机器进行回收,回收就涉及到应用迁移,问题是整个过程一团乱。比如服务器A上一堆应用要调用服务器B上一堆服务,结果服务器B被回收了,然后服务器A上一堆应用报错。 今天就是负责查一个问题,app上一个头像上传的接口,之前都好好的,不知道怎么就不能访问了,

一次nginx文件打开数的问题排查处理

现象:nginx域名配置合并之后,发现consul-template无法完成nginx重载,然后发现需要重启nginx,才能让配置生效。 注意:下次哪个服务有报错,就看重启时所有日志输出,各种情况日志输出。不要忽略细节。很多时候其实已经看到了问题,却没有深入查看问题。 查看进程最大打开文件个数 #c

[转帖]总结:nginx502:Tomcat调优之acceptCount

问题背景:UI页面点击会偶尔返回error,检查调用日志,发现nginx报502报错,因此本文即排查502报错原因。 如下红框可知,访问本机个备机的服务502了,用时3秒左右(可见并不是超时) 先给出原因:是因为tomcat8默认的acceptCount是100,请求量大的时候,会将一些来不及处理的

线上问题排查--进程重启失败,最后发现是忘了cd

# 背景 我前面写了几篇文章,讲c3p0数据库连接池发生了连接泄露,但是随机出现,难以确定根因,最终呢,为了快速解决问题,我是先写了个shell脚本,脚本主要是检测服务的接口访问日志,看看过去的30s内是不是接口几乎都超时了,如果是的话,咱们就重启服务。然后把这个shell加入到了crontab里,

问题排查---应用程序不在接收新请求

问题排查 应用程序不在接收新请求 关键词:springboot,jstack,Arthas 问题描述 查看前端网页,发现所有请求都pending,都超时。但是查看后端程序发现并没有挂掉,cpu,内存都正常。但是日志不打印了。看起来应用程序整体卡死了。 然后重启应用程序,发现又能正常运行了,但是过了半

【问题排查篇】一次业务问题对 ES 的 cardinality 原理探究

小编工作中负责业务的一个服务端系统,使用了 Elasticsearch 服务做数据存储,业务运营人员反馈,用户在使用该产品时发现,用户后台统计的订单笔数和导出的订单笔数不一致!对此进行排查并进行总结

[转帖]K8S 问题排查: cgroup 内存泄露问题 - kmem

K8S 问题排查: cgroup 内存泄露问题 - kmemhttps://www.cnblogs.com/leffss/p/15019898.html 目录 前言 现象 原因 解决方案 方案一 方案二 方案三 验证方式 影响范围 原理解释 kmem 是什么 cgroup 与 kmem 机制 kme

线上FullGC问题排查实践——手把手教你排查线上问题

作者:京东科技 韩国凯 一、问题发现与排查 1.1 找到问题原因 问题起因是我们收到了jdos的容器CPU告警,CPU使用率已经达到104% 观察该机器日志发现,此时有很多线程在执行跑批任务。正常来说,跑批任务是低CPU高内存型,所以此时考虑是FullGC引起的大量CPU占用(之前有类似情况,告知用

ELK日志缺失问题排查-多行日志聚合Logstash配置问题

1. 背景 推荐系统的推荐请求追踪日志,通过ELK收集,方便遇到问题时,可以通过唯一标识sid来复现推荐过程 最近在碰到了几个bad case,需要通过sid来查询推荐日志,但发现部分无法在kibana查询到 2. 分析 推荐日志的整个收集流程如下: flowchart LR 线上机器日志 -->