

在智慧档案馆与数据中心项目中,我们曾遭遇一个诡异现象:平台显示数百个以太网温湿度传感器“在线”(Link灯亮、Ping正常),但 Modbus TCP 读数全部停滞,界面曲线呈直线,重启平台采集服务后瞬间恢复,数小时后问题复现。
这不是传感器故障,也不是网络抖动,而是典型的 TCP 连接池耗尽(Connection Pool Exhaustion) 问题。本文完整复盘该问题的定位过程、根因分析与工程化解决方案。
故障表象:
Connection refused、Connection timeout、No buffer space available。 collector 服务,所有数据瞬间恢复,但 2~4 小时后故障重现。 初步误判:
Modbus Poll 直连单台传感器,读取正常。 tcpdump: tcpdump -i eth0 host <sensor_ip> -w cap.pcapTIME_WAIT 状态的 TCP 连接。 netstat -an | grep :502 | wc -l # 结果:接近 65000(系统上限)深入代码发现,采集服务采用了“每次读取都新建连接,读取完立即关闭”的短连接模式。
故障逻辑链:
TIME_WAIT 状态,持续 60 秒(2MSL),确保远端收到确认。 TIME_WAIT 回收速度,端口资源被耗尽。 💡 核心误区:认为 TCP/IP 是“连上网就能用”,忽略了操作系统对并发连接数和端口资源的硬性限制。
虽然问题爆发点在平台,但传感器端的实现方式加剧了这一问题。
工业以太网温湿度传感器通常使用 STM32 + W5500(硬件协议栈)或 LWIP(软件协议栈)。
Connect -> Read -> Close,循环往复。 部分平台在 Modbus TCP 失败后,会频繁发送 SNMP GET 请求。虽然 SNMP 基于 UDP,但如果传感器同时开启了 TCP 服务,频繁的 TCP 连接失败日志会占用 MCU 处理时间,间接影响 UDP 响应。
核心思想:复用 TCP 连接,避免频繁三次握手和四次挥手。
改造前:
while True:
sock = socket.create_connection((ip, 502))
send_modbus_request(sock)
recv_modbus_response(sock)
sock.close() # 触发 TIME_WAIT
sleep(10)改造后(连接池模式):
class ModbusPool:
def __init__(self, ip, min_conn=2, max_conn=5):
self.pool = queue.Queue(max_conn)
for _ in range(min_conn):
self.pool.put(self._new_conn())
def _new_conn(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip, 502))
return sock
def get_conn(self):
try:
return self.pool.get(timeout=2)
except queue.Empty:
return self._new_conn() # 按需扩容
def release_conn(self, sock):
self.pool.put(sock)
# 使用
pool = ModbusPool(ip)
while True:
conn = pool.get_conn()
try:
send_modbus_request(conn)
recv_modbus_response(conn)
except Exception:
conn.close() # 异常时关闭
conn = None
finally:
if conn:
pool.release_conn(conn)
sleep(10)调整内核参数,加速 TIME_WAIT 回收,扩大端口范围。
编辑 /etc/sysctl.conf:
# 开启 TIME_WAIT 复用
net.ipv4.tcp_tw_reuse = 1
# 开启快速回收(NAT环境慎用,建议仅内部网络开启)
net.ipv4.tcp_tw_recycle = 1 # 注意:Linux 4.12+ 已移除该参数,需依赖 tcp_fin_timeout
# 缩短 FIN_WAIT_2 时间
net.ipv4.tcp_fin_timeout = 30
# 扩大本地端口范围
net.ipv4.ip_local_port_range = 10000 65000
# 增加最大文件句柄数(影响Socket数量)
fs.file-max = 1000000执行 sysctl -p 生效。
压测方案:
netstat -an | grep :502 | wc -l 和 CPU 负载。 优化前:
优化后:
TIME_WAIT 堆积。 TIME_WAIT 数量。 这次“假死”复盘揭示了一个深刻的工程真理:网络编程的复杂性不在于“连通”,而在于“持续稳定地连通”。
对于以太网温湿度传感器这类资源受限的工业终端,平台端的连接管理策略往往比传感器本身的性能更关键。通过引入连接池、优化内核参数和调整采集策略,我们不仅解决了“假死”问题,更将系统的承载能力提升了数倍。
💡 核心心法:把传感器当成“珍贵资源”来对待,用连接池去“养护”它,而不是用短连接去“轰炸”它。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。