从一个线上服务器警告谈谈backlog
缘起
双十一如期而至,此时的我因为在处理客户的一个问题已经陷入了忙碌。突然,不断接到驻场实施发来的反馈,都是相同的反馈——"客户端操作缓慢"。
我现在负责的服务器是一台接口服务器,所有的卖家都要通过这台服务器连接到自己的数据库上,不得小觑。于是我立马放下手头的话,打开了我事先安装好的服务器监控软件(netdata),便看到了下面的警告:

其实,作为一个服务器端新手,我并不知道什么意思。但是客户反馈慢啊!屁股一想也知道是因为服务器资源不够了嘛!于是,我立马把一小部分客户的配置切换到了另外一台准备好的服务器上,危机化解了,我擦了一把汗。
所以,什么是tcp accept queue?
通过搜索这个警告,找到了一个叫backlog的关键字,网上很多办法是增大这个值,因为当时双十一已经过去了,客户已经没有那么多单子发货了。所以,也没有验证这个方法是否对不对。但backlog的迷还一直留在我的脑海里。
http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html
直到有一天,我遇到了上面的一篇文章,才对backlog有较为具体的认识。我简单的根据文中的意思介绍下backlog参数。

要搞清楚这个问题,我们必须要先了解下tcp建立链接的三次握手,从图中可以看出,第一次握手是客户端给服务器发送syn,此时服务器进入SYN_RECV状态(也叫未完成链接,对应图中的SYN_RCVD),那么既然是一个服务器,所以接受这样的链接就不是一个,是很多,所以会有一个队列去记录这样的未完成链接,暂且称为syn队列。
第一次握手完成后,服务器会给客户端发送 SYN+ACK,客户端收到后,这个链接在客户端方面已经是ESTABLISHED状态了。客户端接着会给服务器发送ACK,当服务器收到这个ACK的时候,服务器上的该链接由SYN_RECV 状态到ESTABLISHED状态,此时它进入了一个新队列,这里叫它accept队列。顾明思议就是供accept来消耗的请求。
两个队列的长度限制由什么参数决定?
经过上面分析,我们知道服务器端处理的请求链接是有两个队列来控制,syn队列(对应图中的syns queue)是等待客户端回复ack的链接,叫做未完成链接或者半连接,而完成三次握手后,该链接进入accept队列,那么这两个队列的长度是多少呢?

由上图可以看出,syn队列就是由 /proc/sys/net/ipv4/tcp_max_syn_backlog参数来控制。处于这个队列上的链接需要等待的全双工的通信时间,所以如果这个参数开的太小,可能对于一些并发性比较高的http服务器来说,容易成为瓶颈。因为这个syns队列满了以后,新的请求就因为队列满的缘故而被忽略。
而accept函数是有两个参数共同决定的,分别是系统函数listen函数的backlog参数以及内核参数somaxconn,这两者会取最小值,如果应用服务器能够很快的从accept队列中取出任务并执行,这个队列并不会成为负担,但如果每个请求都要耗费很长时间处理的话,那么服务器处理线程将会被打满,这个时候accept队列就会被占满。
accept队列被占满的时候,会引入一个新的问题,那就是此时如果未完成链接接收到客户端的ack完成三次握手,需要转入accept队列,此时该怎么办?此时,如果
tcp_abort_on_overflow参数为0的话,此时服务器什么也不做,忽略掉这次申请转到accept队列的请求。那么这个请求就仍然留在了syns队列,服务器隔断时间会再次发送syn+ack给客户端,也就是说会重复走第二部握手。所以,这里accept队列也应该设置大一些,这样可以省去服务器重复发请求的消耗。
关于syn队列长度的限制,大部分文献说的是由 tcp_max_syn_backlog 参数控制,但也有部分博客有更详细的说明,认为syn队列不仅仅受控制与该参数,带着这个疑问,我也看了些源码:

以上linux源码中,max_qlen_log中代表syn队列的最大长度,sysctl_max_syn_backlog 即是tcp_max_syn_backlog参数的值。第一行的nr_table_entries 是计算这个最大值的因子,它是作为一个参数传入进来的,它是传入的backlog参数,上面已经介绍过backlog参数是内核参数somaxconn和listen函数中传入的backlog的最小值,而通过第一行源码我们可以看出来,这里syn队列的最大值是取backlog 和 tcp_max_syn_backlog的最小值,因此得到以下结论。
syn queue length = min(somaxconn,backlog,tcp_max_syn_backlog)
accept queue length = min(somaxconn,backlog)
实验验证
口说无凭,下面进行一个实验,来按照上面的理论分析下。
准备
OS 云机 1核1G的入门机
服务器是nginx + php-fpm
服务器监控软件netdata
ab压测工具
step 1 : 参数设置
经过上面对两个队列的长度限制分析知道somaxconn参数对两个队列有影响,于是设置somaxconn的值为8,其他backlog参数均为1024。
net.ipv4.tcp_max_syn_backlog = 1024
net.core.somaxconn = 8
net.ipv4.tcp_syncookies = 0
为了避免其他因素的影响我们的测试php文件中只有一句
ehco hello world;
step2: 开始压测
ab 压测 工具并发512个请求,请求总数5120个,请求发送完,发现netdata已经收到了报错信息如下:
step3:得到结果

此时,可以看到两个队列都已经开始drop链接了。
step4:将somaxconn参数为1024,再次相同条件压测发现已经没有警告提示了
结论
通过合理的参数设置,是可以提高服务器报警的门槛,将参数调整到服务器能够承受的最大值,确实可以在一定程度上提高服务器的容量。一方面,队列增大后,可以暂时容纳这些队列,供应用程序消耗。如果队列设置过小,那么新来的链接就会被忽略,客户端还会进行重试,另一方面如果accept很快被充满的话,syn队列会被阻塞,而且syn队列上的链接仍要去消耗资源对客户端重新发送syn+ack,导致一个恶性循环。
但这不意味着尽量调整参数就可以万事大吉了,在一些突发访问的网络中,调大参数可以缓解网络情况,但此时客户端访问服务器肯定不会很快,因为服务器已经陷入了繁忙状态。如果服务器一直处于报警状态,即链接不是突发性的,而是长时间处于一个比较高的数量,那么就需要进行优化了。优化分为两方面,第一方面应用程序的优化,即让每个链接的处理速度加快,这样线程可以快速的释放,accept消耗加快,服务器处理速度加快。另外一方面,就是扩容服务器,通过负载均衡水平扩展计算资源,让链接分配到不同机器上快速消耗。
从一个线上服务器警告谈谈backlog的更多相关文章
- 线上服务器TCP被打满是啥情况
从一个线上服务器警告谈谈backlog https://wangxiangnan.cc/?p=105 缘起 双十一如期而至,此时的我因为在处理客户的一个问题已经陷入了忙碌.突然,不断接到驻场实施发来的 ...
- 记录一次linux线上服务器被黑事件
1.原因:本来在家正常休息了,我们放在上海托管机房的线上服务器突然蹦了远程不了,服务启动不了,然后让上海机房重启了一次,还是直接挂了,一直到我远程上才行. 2.现象:远程服务器发现出现这类信息 Hi, ...
- 线上服务器上安装的VNCServer不能正常工作
1.问题描述: 线上服务器上安装的不能正常工作 2.解决问题过程: 一. 重启vncserver 运行命令:vncserver -kill :1和vncserver :1 二. 发现vncserver ...
- 【效率工具】SSH一键登录脚本(可一键从跳板机登录线上服务器)
说明 前阵子上线,一次性上了十个服务,一直上到凌晨才完事,期间每个服务都要先输入跳板机的登录信息来登录跳板机,然后再输入线上服务器的信息来登录线上服务器,实在是太过于麻烦,而且有些服务还有好几台服务器 ...
- 01 . Go之Gin+Vue开发一个线上外卖应用
项目介绍 我们将开始使用Gin框架开发一个api项目,我们起名为:云餐厅.如同饿了么,美团外卖等生活服务类应用一样,云餐厅是一个线上的外卖应用,应用的用户可以在线浏览商家,商品并下单. 该项目分为客户 ...
- 线上服务器CPU100%排查,Linux进程消耗查看
线上服务器CPU100%排查,Linux进程消耗查看 1.排查步骤 1.1Linux下排查 1.1.1查消耗cpu最高的进程PID 1.1.2根据PID查出消耗cpu最高的线程号 1.1.3根据线程号 ...
- 分享下使用 svn,测试服务器代码自动更新、线上服务器代码手动更新的配置经验
分享下使用 svn,测试服务器代码自动更新.线上服务器代码手动更新的配置经验 利用SVN的POST-COMMIT钩子自动部署代码 Linux SVN 命令详解 Linux SVN 命令详解2 使用sv ...
- 本地数据库导入线上服务器的mongodb中
更改默认端口 sudo vi /etc/mongod.conf 进入conf文件,修改port值为19999保存并退出. 重启mongodb sudo service mongod restart 进 ...
- 线上服务器CPU彪高的调试方式
原文内容来自于LZ(楼主)的印象笔记,如出现排版异常或图片丢失等问题,可查看当前链接:https://app.yinxiang.com/shard/s17/nl/19391737/2fee7b91-f ...
随机推荐
- “标准查询运算符”是组成语言集成查询 (LINQ) 模式的方法
“标准查询运算符”是组成语言集成查询 (LINQ) 模式的方法.大多数这些方法都在序列上运行,其中的序列是一个对象,其类型实现了IEnumerable<T> 接口或 IQueryable& ...
- ExtJS4 ajax请求同步异步问题
今天在写代码过程中遇到一个奇怪的问题.事情是这种,我写了一个简单的页面用来删除选中的用户,请看以下: 由于后台的servlet的代码实现了依据用户名来删除一条记录.所以我在前台的ExtJS代码里面用了 ...
- POJ 1088 滑雪 【记忆化搜索经典】
题目链接:http://poj.org/problem?id=1088 滑雪 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: ...
- 基于Qt搭建ROS开发环境
参考的博客: http://blog.csdn.net/u013453604/article/details/52186375 http://blog.csdn.net/dxuehui/article ...
- mybais学习记录一——入门程序
一.传统连接数据库和执行sql的不足 1.数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响 数据库性能. 设想:使用数据库连接池管理数据库连接. 2. ...
- 【luogu P3950 部落冲突】 题解
题目连接:https://www.luogu.org/problemnew/show/P3950 1.像我这种学数据结构学傻了的 2.边权化点权 所有点权初始化0 3.对于战争 将深度较深的-1,对于 ...
- Android学习笔记_9_SQLiteOpenHelper对象之数据库增删改查以及事务回滚操作
一.SQLite数据库: 在Android平台上,集成了一个嵌入式关系型数据库—SQLite,SQLite3支持 NULL.INTEGER.REAL(浮点数字).TEXT(字符串文本)和BLOB(二进 ...
- Openresty最佳案例 | 第2篇:Lua入门
转载请标明出处: http://blog.csdn.net/forezp/article/details/78616622 本文出自方志朋的博客 什么是lua Lua 是一种轻量小巧的脚本语言,用标准 ...
- About Unity3D 4.1.2 (to continue…)
Here are something that need to take care of when you work with Unity3D: 1) It seems Unity3D could c ...
- FirstBird--项目流程
创建项目(英文路径)—–img图片文件 创建窗体–设置大小(Basic—size–>320*480)—最大化功能禁用(Expert–>setResizable(false)) 添加面板–设 ...