linux tcp 异常断开连接,TCP 异常断开

首先感谢你这么详细的提问!

如果业务每个请求处理时间都足够快,支持8万设备在线是没问题的。

但是如果业务有一点慢,比如数据库操作一次需要0.05秒,假设8万设备每秒产生5000个操作数据库的请求,那么设备每秒产生的请求需要服务端耗时25秒才能处理完(多进程的情况下可以缓解),这样请求不断累积会出现业务延迟越来越严重。如果客户端设备有做超时断开操作,那么可能会导致大面积连接断开重连。往坏一点说,如果某些请求处理更慢些,例如慢sql 访问外部存储或者curl超时阻塞了几十秒,那个情况会变得更差。所以保证每个请求都能极快的处理是保持上万并发连接的关键。

目前总结的客户端连接断开的原因大概有以下几个方面:

1、设备所处环境网络不稳定

2、设备与服务器间没有用心跳来维持连接。心跳间隔最好小于60秒,大于60秒的心跳无法有效维持连接,有些可能需要的心跳间隔更小。

3、没有安装event扩展,导致单个进程无法维持超过1024个连接,多余的连接会有超时断开的情况

4、没有按照手册优化linux内核

例如内核进程打开文件数限制了单个进程只能维持1024个连接,多余连接超时断开

例如内核同时打开了net.ipv4.tcp_tw_recycle 和 net.ipv4.timestamp 导致处于nat网络的客户端连接超时

例如内核防火墙跟踪表 (net.netfilter.nf_conntrack_max)大小设置太低,无法应对大量连接,导致客户端连接超时或者断开

5、业务bug导致一些连接被错误的断开

6、设备bug导致连接断开

根据描述,白天设备连接断开比较频繁,夜晚比较稳定,我有点怀疑是由于白天很多用户活动与不同的环境导致,例如在电梯 地铁 地下室等环境网络比较差,连接断开。等到了信号好的地方又重新连接。

而夜里时大家都在睡觉,不会出现网络环境频繁变更的情况,自然比较稳定。

Linux环境下,当TCP客户端异常断开连接时,服务器通常通过监听socket(套接字)的状态变化来检测到这个情况。以下是一些常用的方法: 1. **异常关闭检测**:在服务器端,可以设置非阻塞模式接收,这样当客户端断开连接时,read()操作会立即返回错误,如EBADF(文件描述符无效)。然后检查返回码,判断是否为异常。 ```c int flags = fcntl(sockfd, F_GETFL, 0); fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); // 设置非阻塞模式 ssize_t bytes_received; if (bytes_received = read(sockfd, buffer, sizeof(buffer))) { if (bytes_received == 0) { // 客户端正常关闭 close(sockfd); // 关闭连接 } else if (errno != EAGAIN && errno != EWOULDBLOCK) { // 异常断开,如ECONNRESET等 perror("Error reading from client"); } } else { perror("Client disconnected"); } ``` 2. **心跳机制**:服务器定期向客户端发送心跳包(例如,空数据包或特定标识),如果长时间未收到响应,则认为客户端断开。 3. **超时处理**:使用select/poll/epoll等系统调用来监控socket,当连接挂起一段时间无读写活动时,可以判断为断开。 4. **使用长连接和keep-alive选项**:开启TCP的keep-alive选项可以在一段时间内自动探测连接是否中断,如果没有收到客户端的数据包,服务器将发起探查。 在上述操作中,每种方法都有其适用场景和局限性。为了获得更准确的诊断信息,服务器通常结合多种策略来检测并处理异常断开的情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值