缓存服务器syns to listen sockets drop导致创建socket失败

本文涉及的产品
公网NAT网关,每月750个小时 15CU
简介: 问题描述: 最近遇到了一个syn丢包的情况,当系统磁盘、网络、cpu都无压力的时候,系统莫名其妙出现“sync to listen sockets drop”问题;无论带宽是10M还是8G,都会出现这种这种情况。
问题描述:
最近遇到了一个syn丢包的情况,当系统磁盘、网络、cpu都无压力的时候,系统莫名其妙出现“sync to listen sockets drop”问题;无论带宽是10M还是8G,都会出现这种这种情况。现象为:输入系统命令:netstat -s | grep LISTEN,会出现 syns to listen sockets dropped; 但是并没有times the listen queue of a socket overflowed;连接队列包括两种,一个是半连接队列(syn queue),一个是全连接队列(accept queue);根据上述描述,accept队列并没有溢出,而syn队报丢失有可能是syn队列溢出的原因,也可能是其他原因;"syns to listen sockets dropped"意思是:收到三次握手的ack包,因为各种原因导致创建socket的过程中被丢弃;
首先我们分析了一下netstat -s里面的数据,发现"passive connections rejected because of time stamp"的值和"syns to listen sockets dropped"相差不大,很多服务器他们的值都是相同的,这个让人感觉sync to listen sockets drop的原因有可能与时间戳有关;
我们检查了一下系统的配置:
or的keepalive设置为512个,总共40个cpu;系统级别的监听队列长度是65535,syn队列是26w;or的每个进程监听队列是20w;
我们的架构是上层是openresty,下层是我们的自研缓存软件;
syns to listen sockets dropped; 是由于在三次握手过程中创建socket失败,但是我们不知道是or或者cache软件作为客户端丢失syn包还是or或者cache软件作为服务器丢失syn包;于是我们做了一系列测试;
发现以下几点:
1. client(用户)访问or层,会导致or层作为服务器端的syn包丢失;
2. or作为客户端,访问cache软件时,or发出的syn包没有丢失;(or和cache软件是同一个机房);
3. cache软件作为服务器,接受到的syn包没有丢失;
4. cache软件作为客户端,发出去的syn包没有丢失(cache软件主要是给其他IDC发送http请求);
于是我们的重点是解决用户给or的syn包丢失的问题;
我们从网上查找原因,查到了最有可能的原因:
因为2.6内核以上中tcp_timestamps默认是打开的,所以当打开 tcp_tw_recycle时会导致部分通过NAT上网client无法正确连接服务器,故障表现为client发出SYN后无法收到server返回 的SYN+ACK,推荐的解决方法是关闭tcp_tw_recycle,打开tcp_tw_reuse解决TIME-WAIT过多的问题。
我们将/proc/sys/net/ipv4/tcp_tw_recycle修改为0,drop情况就不发生了;
然后查看tw个数:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
下面我们总结一下:
tcp_tw_recycle 设置为 1 会开启系统对 TIME_WAIT 状态的 socket 的快速回收。开启这个功能,系统就会存下 TCP 连接的时间戳,当同一个 IP 地址过来的包的时间戳小于缓存的时间戳,系统就直接丢包,“回收”这个 socket。这个选项同样需要开启 tcp_timestamp 才生效。
开启这个功能是有很大风险的,服务器端会根据同一个 IP 发送过来的包的时间戳来判断是否丢包,而时间戳是根据发包的客户端的系统时间得来的,如果服务端收到的包是同一出口 IP 而系统时间不一样的两个客户端的包,就有可能会丢包,可能出现的情况就是一个局域网内有的客户端能连接服务端,有的不能。具体原因是客户端处于NAT模式下,出口ip可能是同一个ip,不同客户端的发送的时间戳可能乱序,服务器会检查相同ip地址发送来过的包的时间戳是不是小于缓存的时间戳,如果不是,直接丢掉;
有可能drop package的情况:(服务器端tcp_tw_recycle和tcp_timestamp都开启)
1.lvs处于NAT模式(咱们是DR);
2.客户端处于NAT模式;
3.IDC处于NAT模式;有人对国内的节点做了一个可视化分析,发现有2.61%的概率出口存在NAT的这种情况;
在服务器上最好打开 tcp_tw_reuse,并且关闭tcp_tw_recycle。
tcp_tw_reuse和tcp_tw_recycle区别:
1. tw_reuse,tw_recycle 必须在客户端和服务端timestamps 开启时才管用(默认打开)
2. tw_reuse 只对客户端起作用,开启后客户端在1s内回收
3. tw_recycle 对客户端和服务器同时起作用,开启后在 3.5*RTO 内回收,RTO 200ms~ 120s 具体时间视网络状况。内网状况比tw_reuse 稍快,公网尤其移动网络大多要比tw_reuse 慢,优点就是能够回收服务端的TIME_WAIT数量;

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
相关文章
|
1月前
|
缓存 监控 Java
Java Socket编程最佳实践:优化客户端-服务器通信性能
【6月更文挑战第21天】Java Socket编程优化涉及识别性能瓶颈,如网络延迟和CPU计算。使用非阻塞I/O(NIO)和多路复用技术提升并发处理能力,减少线程上下文切换。缓存利用可减少I/O操作,异步I/O(AIO)进一步提高效率。持续监控系统性能是关键。通过实践这些策略,开发者能构建高效稳定的通信系统。
|
1月前
|
IDE Java 开发工具
从零开始学Java Socket编程:客户端与服务器通信实战
【6月更文挑战第21天】Java Socket编程教程带你从零开始构建简单的客户端-服务器通信。安装JDK后,在命令行分别运行`SimpleServer`和`SimpleClient`。服务器监听端口,接收并回显客户端消息;客户端连接服务器,发送“Hello, Server!”并显示服务器响应。这是网络通信基础,为更复杂的网络应用打下基础。开始你的Socket编程之旅吧!
|
1月前
|
Java
Java Socket编程与多线程:提升客户端-服务器通信的并发性能
【6月更文挑战第21天】Java网络编程中,Socket结合多线程提升并发性能,服务器对每个客户端连接启动新线程处理,如示例所示,实现每个客户端的独立操作。多线程利用多核处理器能力,避免串行等待,提升响应速度。防止死锁需减少共享资源,统一锁定顺序,使用超时和重试策略。使用synchronized、ReentrantLock等维持数据一致性。多线程带来性能提升的同时,也伴随复杂性和挑战。
|
1月前
|
安全 Java 网络安全
Java Socket编程教程:构建安全可靠的客户端-服务器通信
【6月更文挑战第21天】构建安全的Java Socket通信涉及SSL/TLS加密、异常处理和重连策略。示例中,`SecureServer`使用SSLServerSocketFactory创建加密连接,而`ReliableClient`展示异常捕获与自动重连。理解安全意识,如防数据截获和中间人攻击,是首要步骤。通过良好的编程实践,确保网络应用在复杂环境中稳定且安全。
|
2天前
|
Java
如何在Java中实现多线程的Socket服务器?
在Java中,多线程Socket服务器能同时处理多个客户端连接以提升并发性能。示例代码展示了如何创建此类服务器:监听指定端口,并为每个新连接启动一个`ClientHandler`线程进行通信处理。使用线程池管理这些线程,提高了效率。`ClientHandler`读取客户端消息并响应,支持简单的文本交互,如发送欢迎信息及处理退出命令。
|
24天前
|
缓存 应用服务中间件 Apache
缓存代理服务器的实现机制和技术选型
缓存代理服务器是一种特殊的代理服务器,其主要功能是缓存从目标服务器(通常是Web服务器)获取的数据,并在客户端再次请求相同数据时直接提供缓存的数据。通过缓存代理服务器可以加快访问速度并减轻目标服务器的负载。
|
1月前
|
Java 数据安全/隐私保护
深入剖析:Java Socket编程原理及客户端-服务器通信机制
【6月更文挑战第21天】Java Socket编程用于构建网络通信,如在线聊天室。服务器通过`ServerSocket`监听,接收客户端`Socket`连接请求。客户端使用`Socket`连接服务器,双方通过`PrintWriter`和`BufferedReader`交换数据。案例展示了服务器如何处理每个新连接并广播消息,以及客户端如何发送和接收消息。此基础为理解更复杂的网络应用奠定了基础。
|
1月前
|
Java Android开发
Java Socket编程示例:服务器开启在8080端口监听,接收客户端连接并打印消息。
【6月更文挑战第23天】 Java Socket编程示例:服务器开启在8080端口监听,接收客户端连接并打印消息。客户端连接服务器,发送"Hello, Server!"后关闭。注意Android中需避免主线程进行网络操作。
49 4
|
17天前
|
Java 数据格式
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
18 0
|
1月前
|
网络协议 Java Linux
探索Java Socket编程:实现跨平台客户端-服务器通信的奥秘
【6月更文挑战第21天】Java Socket编程示例展示了如何构建跨平台聊天应用。服务器端使用`ServerSocket`监听客户端连接,每个连接启动新线程处理。客户端连接服务器,发送并接收消息。Java的跨平台能力确保代码在不同操作系统上无需修改即可运行,简化开发与维护。