性能分析之TCP全连接队列占满问题分析及优化过程(转载)
前言
在对一个挡板系统进行测试时,遇到一个由于TCP全连接队列被占满而影响系统性能的问题,这里记录下如何进行分析及解决的。
理解下TCP建立连接过程与队列
从图中明显可以看出建立 TCP 连接的时候,有两个队列:syns queue
(半连接队列)和accept queue
(全连接队列),分别在第一次握手和第三次握手。
半连接队列: 保存 SYN_RECV 状态的连接。
控制参数:
半连接队列的大小:min(backlog, 内核参数 net.core.somaxconn,内核参数tcp_max_syn_backlog).
net.ipv4.tcp_max_syn_backlog:能接受 SYN 同步包的最大客户端数量,即半连接上限;
tcp_syncookies:当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
accept队列-全连接队列:保存 ESTABLISHED 状态的连接。
控制参数:
全连接队列的大小:min(backlog, /proc/sys/net/core/somaxconn),意思是取backlog 与 somaxconn 两值的最小值,
net.core.somaxconn
定义了系统级别的全连接队列最大长度,而 backlog 只是应用层传入的参数,所以 backlog 值尽量小于net.core.somaxconn
;net.core.somaxconn
(内核态参数,系统中每一个端口最大的监听队列的长度);net.core.netdev_max_backlog
(每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目);ServerSocket(int port, int backlog) 代码中的backlog参数;
文件句柄;
net.ipv4.tcp_abort_on_overflow
= 0,此值为 0 表示握手到第三步时全连接队列满时则扔掉 client 发过来的 ACK,此值为 1 则说明握手到第三步时全连接队列满时则返回 reset 给客户端。
系统概况
系统的整体架构比较简单,只有一个挡板服务,业务功能主要是接受业务数据写入日志文件,并加了 35 ms的延时等待,没有复杂的运算等业务逻辑。
开始第一次压测
以 6000 线程并发,加 1 秒的等待,对挡板服务发起压力,压测结果如下:
PS:应客户要求,为了模拟真实业务场景,用较大并发进行测试。
通过上图可以看出,当系统吞吐量也就是 TPS 达到 3800 左右的时候,系统开始出现部分请求失败,继续压一段时间后,报错没有减少,且有增多的趋势。这是什么原因导致的呢,接着我也观察了下,系统的资源使用情况,发现CPU也不是很高,那可以先排除系统CPU资源的问题。
这时候,我们一定要记住,当出现请求事务大量失败的时候,一定要先看以下具体的错误信息,在继续往下面分析,而不是进行盲目的猜测,这里要提一下高楼老师经常强调的证据链,一定要根据详细的错误信息指向进行下一步分析,不能根据猜测进而通过修改一些参数,或者增加系统资源来解决问题。
以下是具体的报错信息:
看到报错信息后,发现有大量的 “Connection reset” 错误,导致这种错误的原因就是服务端因为某种原因关闭了 Connection,而客户端仍然在读写数据,此时服务器会返回复位标志 “RST”,也就是刚才提到的 `“java.net.SocketException: Connection reset”。参考 Oracle 的相关文档,看到这么一段话,原文如下:
By contrast, an abortive close uses the RST (Reset) message. If either side issues an RST, this means the entire connection is aborted and the TCP stack can throw away any queued data which has not been sent or received by either application.
翻译过来也就是说:
如果任何一方发出RST,这意味着整个连接被中止,TCP栈可以丢弃任何没有被任何应用程序发送或接收的队列数据。
这样的话,问题就很明显了,接下来看下 TCP 连接队列的溢出数据统计情况,命令为:“netstat -s
”
# 查看TCP半连接队列溢出:
netstat -s | grep LISTEN
# 查看TCPaccept队列溢出:
netstat -s | grep overflow
通过反复敲命令,可以看出这个 overflow 的值一直在增加,那么这个现象说明 server 的TCP 全连接队列的确是满了。这时候应该想到的是,全连接队列已经溢出了,下一步就应该看一下,全连接队列的占用情况,命令为:
参数说明:
Recv-Q:全连接当前长度
Send-Q:如果连接不是在建立状态,则是当前全连接最大队列长度
从上图第三列的 Send-Q
可以看出,5000 端口服务的全连接队列最大为 50,而 Recv-Q
为当前使用了多少。在压测过程中,查看指定端口的 TCP 全连接队列使用情况,如下:
上图可以看出,全连接队列几乎已经被占满,那么最终可以确定问题所在了。找到原因后,现在只要增大全连接队列的长度就可以了。
通过上面介绍的全连接队列中,我们知道全连接队列的大小为 backlog 和 somaxconn 的最小值,那么来看下 somaxconn 的取值。
可以看出 somaxconn 的值是很大的,那就只有通知开发,增加应用代码中的 backlog 的值来加大全连接队列的长度。
调大backlog值为5000后,再次进行压测
调整后的全连接队列如下图所示:
继续以 6000 并发对系统发起压力,测试结果如下:
从上面的测试结果数据看出,已经没有错误请求了,再次查看TCP全连接队列的使用情况,Recv-Q
的值也变得很大,但是仍小于 5000,这也说明之前的 50 的确太小,导致全连接队列被占满,最终影响系统性能,出现大量请求失败,到此,由 TCP 连接队列满导致的问题解决。
但是仔细看上面的 JMeter 的测试结果数据,发现当系统并发达到 4600 多后,再继续加大线程,系统的响应时间开始大幅度的增加,TPS增加趋势变缓,可以看出来此时系统仍存在瓶颈。
发现仍问题后,接着往下分析。系统没有报错,响应时间变长,导致系统吞吐量增长速度变慢。这时应该清楚的是,接下来该看什么。首先查看系统CPU使用情况,发现并不是很高,说明不是系统资源不够用而引起的问题。因为挡板服务本身没有什么业务逻辑,只是加了 35 ms的延时,那么如果响应时间变慢了,那么多半是由于网络传输出现阻塞导致。
所以使用命令:
netstat -ano | grep 10.231.44.249:5000 | grep ESTABLISHED | more
看下网络队列情况:
参数说明:
Send-Q:发送队列中没有被远程主机确认的 bytes 数;
Recv-Q:指收到的数据还在缓存中,还没被进程读取,这个值就是还没被进程读取的
bytes;一般是CPU处理不过来导致的。
可以看出图中标红列的数据不为 0,通过上面的解释可以判断出是系统 CPU 处理不过来了,但是CPU也没有被充分使用,那为什么会出现这种情况呢。接下我们就该看一下,CPU 在做什么。
这里使用阿里的开源工具 arthas(arthas的安装及使用这里不过多介绍了),看下挡板服务是否存在线程的资源争用或者阻塞等,发现结果如下,存在大量的线程状态为 BLOCKED
命令:thread | grep BLOCKED
命令:thread -b
看到具体的线程栈信息后,问题就比较明显了,是一个写日志的锁导致出现线程阻塞,严重影响系统的处理能力。
为了快速的验证是写日志导致的,调整日志级别为 ERROR,再次发起压力,看问题是否解决,测试结果如下:
调整日志级别后,系统的响应时间保持在 37 ms左右,吞吐量有了大幅度的提升,问题解决。
小结
通过上面的分析案例,需注意以下几点:
压测时,如果出现请求大量失败时,记住一定要先解决报错,在进行下一步的分析;
进行性能分析时,一定要找到相应的证据链一步一步的往下分析,而不是盲目的猜测,通过修改参数及加大资源配置来解决问题;
响应时间长,TPS上不去这种问题,一定要对时间进行拆分拆解,找到时间具体慢在哪里,再进行进一步的分析优化。
转自:https://mp.weixin.qq.com/s/Bjjrk85MTTSiHoECNIWEaw
多学一点:
一、查看当前系统下所有连接状态的数
netstat -n|awk '/^tcp/{++S[$NF]}END{for (key in S) print key,S[key]}'
ESTABLISHED 38
TIME_WAIT 1000
二、看下我系统上默认的SYN队列大小
[root@log]# cat /proc/sys/net/ipv4/tcp_max_syn_backlog
262144
定义SYN队列大小:
echo 4096 > /proc/sys/net/ipv4/tcp_max_syn_backlog --定义是php配置的两倍,大于php的就行
三、看下我系统上默认的TIME_WAIT队列大小
cat /proc/sys/net/ipv4/tcp_max_tw_buckets
1000
定义TIME_WAIT的大小:
echo 4096 > /proc/sys/net/ipv4/tcp_max_tw_buckets
四、修改backlog参数
Kernel会为LISTEN状态的socket维护两个队列,一个是SYN RECEIVED状态,另一个是ESTABLISHED状态,而backlog就是这两个队列的大小之和。
当前Linux版本使用上面说法,有两个队列:具有由系统范围设置指定的大小的SYN队列 和 应用程序(也就是backlog参数)指定的accept队列。
五、查看系统默认数量:
cat /proc/sys/net/core/netdev_max_backlog
定义队列的数据包的最大数目
echo "4096" > /proc/sys/net/core/netdev_max_backlog #在每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。
六、nginx 配置参数优化:
有代理就设置在代理上:没有代理就直接设置在web应用上(或者两个都设置)
upstream js_sdk {
#ip_hash;
server ******* weight=1 max_fails=3 fail_timeout=10s;
server ******* weight=1 max_fails=3 fail_timeout=10s;
keepalive 1000;
}
server {
listen 80 default backlog=1024;
listen 443 ssl default backlog=1024;
七、php优化:(-1 表示没有使用系统的 backlog )
vim /usr/local/php/etc/php-fpm.conf
listen.backlog = 2048 #每一个端口最大的监听队列的长度,需要配置nginx配置文件使用,如下(暂时只更改这里)
八、linux内核参进行优化:
vim /etc/sysctl.conf
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 4096 #对于还未获得对方确认的连接请求,可保存在队列中的最大数目。如果服务器经常出现过载,可以尝试增加这个数字。
net.core.somaxconn = 4096 #定义了系统中每一个端口最大的监听队列的长度,这是个全局的参数。backlog需要设置这个
使用命令使之生效:sysctl -p
转自:https://blog.csdn.net/u010917150/article/details/95621873
性能分析之TCP全连接队列占满问题分析及优化过程(转载)的更多相关文章
- TCP全连接队列和半连接队列已满之后的连接建立过程抓包分析[转]
最近项目需要做单机100万长连接与高并发的服务器,我们开发完服务器以后,通过自己搭的高速压测框架压测服务端的时候,发生了奇怪的现象,就是服务端莫名其妙的少接收了连接,造成了数据包的丢失,通过网上查资料 ...
- 五分钟带你读懂 TCP全连接队列(图文并茂)
爱生活,爱编码,微信搜一搜[架构技术专栏]关注这个喜欢分享的地方. 本文 架构技术专栏 已收录,有各种视频.资料以及技术文章. 一.问题 今天有个小伙伴跑过来告诉我有个奇怪的问题需要协助下,问题确实也 ...
- [TimLinux] TCP全连接队列满
0. TCP三次握手 该图来自:TCP SOCKET中backlog参数的用途是什么? syns queue: 半连接队列 accept queue: 全连接队列 控制参数存放在文件:/proc/sy ...
- TCP 半连接队列和全连接队列满了会发生什么?又该如何应对?
前言 网上许多博客针对增大 TCP 半连接队列和全连接队列的方式如下: 增大 TCP 半连接队列的方式是增大 /proc/sys/net/ipv4/tcp_max_syn_backlog: 增大 TC ...
- TCP实战二(半连接队列、全连接队列)
TCP实验一我们利用了tcpdump以及Wireshark对TCP三次握手.四次挥手.流量控制做了深入的分析,今天就让我们一同深入理解TCP三次握手中两个重要的结构:半连接队列.全连接队列. 参考文献 ...
- 三次握手 四次握手 原因分析 TCP 半连接队列 全连接队列
小结 1. 三次握手的原因:保证双方收和发消息功能正常: [生活模型] "请问能听见吗""我能听见你的声音,你能听见我的声音吗" [原理]A先对B:你在么?我在 ...
- 【转】关于TCP 半连接队列和全连接队列
摘要: # 关于TCP 半连接队列和全连接队列 > 最近碰到一个client端连接异常问题,然后定位分析并查阅各种资料文章,对TCP连接队列有个深入的理解 > > 查资料过程中发现没 ...
- 关于TCP 半连接队列和全连接队列
关于TCP 半连接队列和全连接队列 http://jm.taobao.org/2017/05/25/525-1/ 发表于 2017-05-25 | 作者 蛰剑 | 分类于 网络 ...
- 【转载】socket 的 connect、listen、accept 和全连接队列、半连接队列的原理
转自:http://blog.csdn.net/tennysonsky/article/details/45621341 写在前面: 1. accept 只是从全连接队列拿出一个已经建立好的socke ...
随机推荐
- 最新 朗玛信息java校招面经 (含整理过的面试题大全)
从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.朗玛信息等10家互联网公司的校招Offer,因为某些自身原因最终选择了朗玛信息.6.7月主要是做系统复习.项目复盘.Leet ...
- 线上Storm的worker,executor,task参数调优篇
问题引入: 线上最近的数据量越来越大,出现了数据处理延迟的现象,观察storm ui的各项数据,发现有大量的spout失败的情况,如下: ------------------------------- ...
- 洛谷 题解 P1133 【教主的花园】
$n<=10^5 $ O(n)算法 状态 dp[i][j][k]表示在第i个位置,种j*10的高度的树,且这棵树是否比相邻两棵树高 转移 dp[i][1][0]=max(dp[i-1][2][1 ...
- 小程序部分机型上一个诡异的偶现bug
如上图所示:开始的时候进到下单页面,价格是0,当选中了商品产生价格的时候,生成的价格如 ¥150,这个时候会只露出¥1以及一小半的5,后面的都被遮挡住了. wxml里是这样的写的 <view w ...
- 【leetcode算法-简单】9. 回文数
[题目描述] 判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数. 示例 1: 输入: 121输出: true示例 2: 输入: -121输出: false解释: ...
- [转帖]三款Nehalem至强5500塔式服务器横评对决(4)
三款Nehalem至强5500塔式服务器横评对决(4) http://tech.sina.com.cn/b/2009-12-14/05051172233_4.shtml 可以看到两路服务器的设置 基本 ...
- 虚拟机(VM)安装openwrt-koolshare软路由
⒈创建虚拟机 **软路由选择Windows操作系统,因为我们需要在PE环境中进行软路由的写入,固件类型选择BIOS,网络类型选择使用仅主机模式网络,虚拟磁盘类型选择IDE[一定要选择IDE模式],SC ...
- 剑指offer42:数组和一个数字S,输出两个数的乘积最小的
1 题目描述 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 输出描述: 对应每个测试案例,输出两个数,小的先输出. ...
- golang glog
原文链接:https://blog.csdn.net/u010857876/article/details/79094942 Flush log 产生后,会暂存在内存的buffer中.只有显示的调用 ...
- 数据库分库分表策略之MS-SQL读写分离方案
MS-SQL读写分离将从以下知识点进行展开: 以下截图内容来自博主:https://www.cnblogs.com/echosong/p/3603270.html 1.本地发布(写库如:centerd ...