TCP的socket资源被耗尽的问题
一、 故障现象
部分机顶盒用户出现大面积登录APP时,界面停留在登陆页面,无反应。
二、 现象初步分析
本次问题出现时,所有AAA出现了异常流量波动,在AAA异常流量段期间接到用户故障报障。此时主要表现在LVS集群显示真实的EPG 服务器不停的被踢出集群和加入(UP/DOWN),导致了用户调度到EPG后出现了异常显示。
AAA异常流量图

三、 问题排查过程
接到故障后第一时间对AAA/EPG后台日志进行了查看,发现用户接入认证和响应都正常,观察到EPG 的LVS集群中有服务器的inactive连接数异常并且随机出现不同EPG服务器被踢出和加入集群,随后对EPG 的LVS集群的状态进行了跟踪和抓包分析,为了快速恢复业务随后重启了EPG tomcat并进行了LVS的主备切换,业务故障恢复。
四、 诊断分析结果
出现故障时通过LVS的日志可以看到5台EPG服务器在轮询的出现连接失败和连接成功的情况,也就是一台OK后,另一台出现连接失败,如此反复的表现在5台EPG服务器上

此时被UP/DOWN的EPG会出现大量的inactive

此时对集群出现UP/DOWM的服务器进行抓包,发现客户端发出了SYN报
文,但是EPG服务器没有响应,并且响应报文发不出去不停的retransmission。

进一步查看该EPG的资源消耗情况netstat发现大量的SYN-RECV

通过上面的现象判断是EPG的socket资源被耗尽进而出现了响应客户端异常,导致了LVS检测EPG服务器异常,因集群是5台EPG服务器,一台异常后LVS集群把用户调度到其它EPG服务器,此时异常用户也对该服务器产生了影响出现了该服务器也被资源耗尽,依次循环。根据当前的用户量程度来看一般EPG的资源应该是可以满足,进一步查看资源情况发现是EPG的句柄数被耗尽导致的,当重启EPG后,资源被释放句柄数被释放问题故障就恢复了。查看EPG服务器发现系统的默认句柄数为1024。
LVS原理分析:
当有异常用户访问EPG时,SYN消息先发送到LVS,LVS会建立一个调度表,显示用户与EPG的TCP对应关系,EPG会直接返回ACK给用户端不经过LVS,只有LVS收到用户端发送的FIN时,表项的对应关系才会删除该用户客户端的EPG对应关系。
当用户访问突然异常且量大的时候EPG默认的句柄数只有1024,这样会导致LVS踢出该EPG,但是此时LVS建立的表里面的TCP关系还在所以inactive数会变的特别大,根据LVS调度策略用户会被调度到其它EPG真实服务器,这样就会形成恶性循环,所有集群的EPG真实服务器会被资源耗尽。
五、处理优化措施
从上述分析来看本次故障根本原因是EPG真实服务器的句柄数采用默认的1024,一旦出现异常用户访问的时候就会变的脆弱,目前修改为了204800。经过本次故障,对系统的参数做了确认和文档化
六、参数修改记录
修改记录一:net.ipv4.tcp_timestamps = 0
原因如下
1、slb服务器为了优化性能,调整以下内核参数:
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_recycle = 1
当这两个参数都打开时,tcp需要校验syn包的时间戳(timestamp)对集团用户有影响使其接入失败。
2、当满足以下条件,syn包将会被忽略,不会回复ack包:
a、该源ip的上次tcp通讯发生在60s内。
b、该源ip的上次tcp通讯的timestamp 大于本次tcp。
注:tcp通讯的timestamp 为系统启动到当前的时间。
3、解释现象:
a、为什么普通的用户播放正常,集团用户不行?
一个ip对应一个普通用户,那么普通用户的tcp通讯的timestamp是一直增大的,即不会满足2中的b条件。
集团用户是做了NAT的,一个ip对应多个客户端,只有tcp通讯的timestamp比较大的客户端(大堂)才能请求成功,timestamp比较小的(房间)请求就失败。
b、房间偶尔又能播放?
该源ip的上次tcp通讯发生在60s之外了。
修改记录二:net.ipv4.tcp_max_tw_buckets = 5000
TIME_WAIT状态的连接过多,会影响到大并发。
修改记录三:net.ipv4.tcp_synack_retries = 0
net.core.somaxconn = 65535
原因如下:
SYN Flood(TCP洪水攻击优化)
tcp_synack_retries:表示回应第二个握手包(SYN+ACK包)给客户端IP后,如果收不到第三次握手包(ACK包)后,不进行重试,加快回收“半连接”,不要耗光资源。可以把tcp_synack_retries改为0,因为客户端还有tcp_syn_retries参数,默认是5,即使服务器端没有重发SYN+ACK包,客户端也会重发SYN握手包。
net.core.somaxconn:最大的监听队列的长度,默认限制为128,在高突发的请求中可能会导致链接超时或触发重传。
修改记录四:
括号值为修改后的值,(X)代表删除。
net.ipv4.tcp_fin_timeout = 5 (1)
net.ipv4.tcp_max_syn_backlog = 10240(262144)
net.ipv4.tcp_max_tw_buckets = 5000(6000)
net.ipv4.tcp_mem = 24794688 33059584 49589376 (X)
net.ipv4.tcp_retries1 = 3 (2)
net.ipv4.tcp_retries2 = 15(2)
net.ipv4.tcp_keepalive_intvl = 75(2)
net.ipv4.tcp_keepalive_probes = 9(3)
net.ipv4.tcp_keepalive_time = 7200(2)
net.ipv4.tcp_rmem = 4096 87380 4194304(X)
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_timestamps = 0(1)// timestamps可单独起效
net.ipv4.tcp_tw_recycle = 1(0)// 需要timestamps起效,此项才奇效,单独开启无意义
net.ipv4.tcp_wmem = 4096 16384 4194304(X)
net.ipv4.udp_mem = 24794688 33059584 49589376(X)
net.ipv4.udp_rmem_min = 4096(X)
net.ipv4.udp_wmem_min = 4096(X)
net.core.rps_sock_flow_entries = 65535
// nf_conntrack 避免iptables的conntrack模块故障
net.netfilter.nf_conntrack_acct = 0
net.netfilter.nf_conntrack_checksum = 1
net.netfilter.nf_conntrack_events = 1
net.netfilter.nf_conntrack_events_retry_timeout = 5
net.netfilter.nf_conntrack_expect_max = 256
net.netfilter.nf_conntrack_generic_timeout = 6
net.netfilter.nf_conntrack_helper = 1
net.netfilter.nf_conntrack_icmp_timeout = 3
net.netfilter.nf_conntrack_log_invalid = 0
net.netfilter.nf_conntrack_max = 524288
net.netfilter.nf_conntrack_tcp_be_liberal = 0
net.netfilter.nf_conntrack_tcp_loose = 1
net.netfilter.nf_conntrack_tcp_max_retrans = 2
net.netfilter.nf_conntrack_tcp_timeout_close = 5
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 6
net.netfilter.nf_conntrack_tcp_timeout_established = 5
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 3
net.netfilter.nf_conntrack_tcp_timeout_last_ack = 3
net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 3
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 3
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 3
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 2
net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 3
net.netfilter.nf_conntrack_timestamp = 0
net.netfilter.nf_conntrack_udp_timeout = 3
net.netfilter.nf_conntrack_udp_timeout_stream = 3
net.nf_conntrack_max = 524288
修改记录五:
net.ipv4.tcp_max_tw_buckets = 6000 (262144)
原因:tcp_max_tw_buckets的默认值为262144
修改记录六:
增加修改文件句柄数:在/root/.bash_profile增加ulimit -n 204800
TCP的socket资源被耗尽的问题的更多相关文章
- Linux配置支持高并发TCP连接(socket最大连接数)
Linux配置支持高并发TCP连接(socket最大连接数) Linux配置支持高并发TCP连接(socket最大连接数)及优化内核参数 2011-08-09 15:20:58| 分类:LNMP&a ...
- 网络编程懒人入门(八):手把手教你写基于TCP的Socket长连接
本文原作者:“水晶虾饺”,原文由“玉刚说”写作平台提供写作赞助,原文版权归“玉刚说”微信公众号所有,即时通讯网收录时有改动. 1.引言 好多小白初次接触即时通讯(比如:IM或者消息推送应用)时,总是不 ...
- TCP/IP Socket发送接收图片demo
一个实例通过client端和server端通讯 客户端通过TCP/IP传输资源文件,比如图片,文字,音频,视频等..... 服务端接受到文件存入本地磁盘,返回接受到:“收到来自于"+s.ge ...
- 【转帖】计算机网络协议(三)——UDP、TCP、Socket
计算机网络协议(三)——UDP.TCP.Socket 2019年09月04日 11:09:41 to_be_better_one 阅读数 28794 文章标签: 计算机网络UDPTCPSocket 更 ...
- 基于TCP协议Socket通信
服务器线程处理类 package demo4; import java.io.*; import java.net.Socket; /** * 服务器线程处理类 * @ClassName Server ...
- Winfrom 基于TCP的Socket 编程
基于TCP的Socket基础例子 服务端的代码 public partial class Form1 : Form { public Form1() { InitializeComponent(); ...
- Http、tcp、Socket连接区别
转自Http.tcp.Socket连接区别 相信不少初学手机联网开发的朋友都想知道Http与Socket连接究竟有什么区别,希望通过自己的浅显理解能对初学者有所帮助. 1.TCP连接 要想明白Sock ...
- 启动redis出现Creating Server TCP listening socket *:6379: bind: No such file or directory
E:\redis>redis-server.exe redis.windows.conf [8564] 10 Oct 20:00:36.745 # Creating Server TCP lis ...
- creating server tcp listening socket 127.0.0.1:6379: bind No error
参考链接:https://blog.csdn.net/n_fly/article/details/52692480 1.window10环境下面安装的redis,之前安装好弄了一下,过了好几天,再次使 ...
随机推荐
- 浏览器对CSS小数点的解析——坑
在写移动端项目时,为了将一个元素垂直居中,于是我将元素的高和行高设置成一样的,但是显示出来的结果,却让人不得其解,如下: 可以看到按钮的底部有一条缝隙,一开始以为是代码写错了,于是检查了一下,发现没啥 ...
- scala-02-数组的操作
scala中的数组和 java中的数组一样, 定义了长度后不可改变 1, 产生一个数组: 有3种创建数组的方式, 分别直接new, 直接赋值, 或者使用 Array中的rang来产生 /** * 获取 ...
- Linux-(watch,at,crontab)
watch命令 1.命令格式: watch [参数] [命令] 2.命令功能: 可以将命令的输出结果输出到标准输出设备,多用于周期性执行命令/定时执行命令. watch可以帮你监测一个命令的运行结 ...
- 开启linux远程访问权限
摘要:今天在Linux服务器上安装了msyql数据库,在本地访问的时候可以访问,但是我想通过远程的方式访问的时候就不能访问了,查询资料后发现,Linux下MySQL默认安装完成后只有本地访问的权限,没 ...
- 面试:C++输入数据
最近在做笔试题,相比与leetcode,笔试题都是要自己写输入输出的,每次在这里都浪费了不少时间,这篇文章总结了一下在C++中怎么向数组中输入数据. 1. 先输入数组大小,然后输入数据数据,中间以空格 ...
- console 调试技巧
前言 如果统计一番前端最常用的方法,那么 console.log 一定位列其中.无论你写的是原生 JS 亦或者是 JQuery.Vue等等,调试之时,都离不开 console.log 方法.但是,co ...
- webstorm取消扫描某文件夹,加快打开速度,例如忽略node_modules目录
方法1.如下图所示(只对当前项目有效) 或者 如果要使用这种方法,一种是还没安装依赖的时候先创建node_modules目录然后打开webstorm设置好excluded再安装:另一种是已经安装了依赖 ...
- 【WePY小程序框架实战四】-使用async&await异步请求数据
[WePY小程序框架实战一]-创建项目 [WePY小程序框架实战二]-页面结构 [WePY小程序框架实战三]-组件传值 async await 是对promise的近一步优化,既解决了promise链 ...
- 使用EF CodeFirst连接MySql数据库
如何使用EF CodeFirst连接MySql数据库? 我们这篇文章介绍怎么使用EF连接MySql 作者的环境 VS2017.Win10.MySql5.x 前言 一般在EF中,默认是使用SqlServ ...
- SQL Server T—SQL 语句【查】
一 查询数据(关键字:select) (1)简单查询 select * from 表名 ——查全表 select 列名 from 表名 select ...