您的位置:首页 > 理论基础 > 计算机网络

如何判断是否丢掉用户请求

2018-02-03 11:58 357 查看
故障背景:
有一个同事找我,他怀疑服务器的http已建立的连接数过多,造成一些请求丢失,从而丢失了日志,但不知道怎么看,让帮忙确认一下。

故障分析:
下面是可能丢数据包的点:
1、交换机
上连和下连端口的流量跑满或链路有问题,有些数据包会被交换机丢掉,抓对应端口的丢包计数值就可以获得这方面的数据。当然,不会每次都丢建立连接的syn数据包,另外,客户端也重传数据包,所以这一块不一定会导致请求数据的丢失,但可以作为参考。

2、负载均衡设备
这个跟上面的交换机类似,但除了有出错的数据包方面的数据,还有出错的连接方面的数据。抓取方法呢,完全设备相关,不在这里说了。

3、操作系统处理不过来,丢弃数据
这里有两部分
第一部分是网卡见操作系统处理不过来,丢数据包,可以读取下面的文件:
/proc/net/dev
每个网络接口一行统计数据,4列是接收出错的数据包数量,5列是接收不过来丢弃的数量。
第二部分是传统非NAPI接口实现的网卡驱动,每个cpu有一个队列,当在队列中缓存的数据包数量超过netdev_max_backlog(sysctl -w net.core.netdev_max_backlog可以修改)限制时,网卡驱动程序会丢掉数据包,这个见下面的文件:
/proc/net/softnet_stat
每个cpu有一行统计数据,第二列是对应cpu丢弃的数据包数量。

4、应用程序处理不过来,操作系统丢弃
内核中记录了两个计数器:
ListenOverflows:此时对应socket的listen queue(或Accept queue)已满,但是三次握手最后一步完成之后需要新增一个连接,这个时候ListenOverflows会加1,即对应应用程序处理不过来的情况。
ListenDrops:包含上面的情况,也就是说当出现ListenOverflows时,它也会增加1;除此之外,当内存不够无法为新的连接分配socket相关的数据结构时,也会增加1,当然还有别的异常情况下会增加1。
对应的数据在下面的文件中:
/proc/net/netstat
21列是ListenOverflows值,22列是ListenDrops值。
用下面命令,可以直接显示这两个数:
cat /proc/net/netstat | awk '/TcpExt/ { print $21,$22 }'
如果是netstat命令,则看包含“times the listen queue of a socket overflowed” “SYNs to LISTEN sockets ignored”这个内容对应行前面的数字。如果没有对应的行,则表明对应的数值为0。如果是0,netstat则不会输出对应的行。

补充几个和三次握手相关的数据
查看网络的连接状态常用的文件是/proc/net/snmp及/proc/net/netstat文件,当你打开这两个文件时,你会出现格式比较乱,因为它里面包含的数据比较多,我们一般用以下两个命令来查看相应的网络状态,其命令为:netstat -s和nstat -az这两个文件中包含的信息较多,这里只简单的写出了几个与三次握手相关的几个参数,并简单地分析了它的含义:TcpAttemptFails:(连接尝试失败数)1. 试图和一个不存在的套接口建立连接时,连接失败,而TcpAttemptFails同时会加12. 被动连接(SYN_SEND)等待第三次握手的ack应答信号超时或者为其它的错误应答时,连接将会失败,且同时TcpAttemptFails的值将加1。TcpExtListenDrops(监听队列连接丢弃数) 1. 首先是查看现有的连接数是否大于设置的backlog,如果大于就丢弃,并相应的参数值加1。其中backlog是由程序和系统参数net.core.somaxconn共同设置,当backlog的值大于系统设置的net.core.somaxconn时则取net.core.somaxconn的值,否则取程序设置的backlog值。这种出错的方式也被记录在TcpListenOverflows中(其只记录了连接个数不足而产生溢出错误的次数!)。TcpListenOverflows(监听队列连接溢出数):1. 接收到连接的应答信号时,但它的源地址和目标不同,或者为空时,这个连接将被丢弃。而TcpListenDrops 值也会加1。2. 当连接没有问题时,系统将会分配必要的资源,而此时没有足够的资源时则会错,此时的连接也会被丢弃,同时TcpListenDrops 值也会加1。3. 最后在新建绑定端口的时候如果出现资源的不足时TcpListenDrops 值也会加1。

ListenOverflows增长的常见原因?

单进程应用程序阻塞,不能 accept 请求。比如 redis 中使用 SORT, LREM, SUNION 这些命令就需要注意。

多进程程序,worker 进程满,不能 accept 请求。比如 apache 或者 php-fpm 多进程模型进程满了。

如何去处理?

ListenOverflows 增长说明应用程序出现了阻塞或者处理不过来的情况,不同问题不同分析。如果是阻塞应当分析阻塞在哪,为什么会阻塞,是否可以缩小阻塞的时间,比如设置更小的连接,读写超时。

如果是应用处理不过来,适当考虑扩容,如果是短时大量的连接可以增加 accept 队列的大小。

参考:

关于tcp listen queue的一点事

linux下socket函数之listen的参数backlog

记一次TcpListenOverflows报警解决过程

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  tcp listen ListenOverflows