从一个线上服务器警告谈谈backlog

https://wangxiangnan.cc/?p=105

缘起
双十一如期而至,此时的我因为在处理客户的一个问题已经陷入了忙碌。突然,不断接到驻场实施发来的反馈,都是相同的反馈——"客户端操作缓慢"。

我现在负责的服务器是一台接口服务器,所有的卖家都要通过这台服务器连接到自己的数据库上,不得小觑。于是我立马放下手头的话,打开了我事先安装好的服务器监控软件(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消耗加快,服务器处理速度加快。另外一方面,就是扩容服务器,通过负载均衡水平扩展计算资源,让链接分配到不同机器上快速消耗

线上服务器TCP被打满是啥情况的更多相关文章

  1. 线上服务器上安装的VNCServer不能正常工作

    1.问题描述: 线上服务器上安装的不能正常工作 2.解决问题过程: 一. 重启vncserver 运行命令:vncserver -kill :1和vncserver :1 二. 发现vncserver ...

  2. 记录一次linux线上服务器被黑事件

    1.原因:本来在家正常休息了,我们放在上海托管机房的线上服务器突然蹦了远程不了,服务启动不了,然后让上海机房重启了一次,还是直接挂了,一直到我远程上才行. 2.现象:远程服务器发现出现这类信息 Hi, ...

  3. 【效率工具】SSH一键登录脚本(可一键从跳板机登录线上服务器)

    说明 前阵子上线,一次性上了十个服务,一直上到凌晨才完事,期间每个服务都要先输入跳板机的登录信息来登录跳板机,然后再输入线上服务器的信息来登录线上服务器,实在是太过于麻烦,而且有些服务还有好几台服务器 ...

  4. 分享下使用 svn,测试服务器代码自动更新、线上服务器代码手动更新的配置经验

    分享下使用 svn,测试服务器代码自动更新.线上服务器代码手动更新的配置经验 利用SVN的POST-COMMIT钩子自动部署代码 Linux SVN 命令详解 Linux SVN 命令详解2 使用sv ...

  5. 本地数据库导入线上服务器的mongodb中

    更改默认端口 sudo vi /etc/mongod.conf 进入conf文件,修改port值为19999保存并退出. 重启mongodb sudo service mongod restart 进 ...

  6. 线上服务器CPU彪高的调试方式

    原文内容来自于LZ(楼主)的印象笔记,如出现排版异常或图片丢失等问题,可查看当前链接:https://app.yinxiang.com/shard/s17/nl/19391737/2fee7b91-f ...

  7. 运维笔记--线上服务器git环境配置

    场景描述: 我们采用git去管理代码分支,本地开发环境,线上服务器多数情况下也会使用git去管理程序代码,那么新的一台服务器,如果指定了目标路径作为代码存放路径,该如何配置git环境, 以达到跟远程服 ...

  8. 线上服务器CPU100%排查,Linux进程消耗查看

    线上服务器CPU100%排查,Linux进程消耗查看 1.排查步骤 1.1Linux下排查 1.1.1查消耗cpu最高的进程PID 1.1.2根据PID查出消耗cpu最高的线程号 1.1.3根据线程号 ...

  9. 从一个线上服务器警告谈谈backlog

    缘起 双十一如期而至,此时的我因为在处理客户的一个问题已经陷入了忙碌.突然,不断接到驻场实施发来的反馈,都是相同的反馈--"客户端操作缓慢". 我现在负责的服务器是一台接口服务器, ...

随机推荐

  1. The same month as the adidas NMD Singapore is releasing

    Earlier this December 2017, the inaugural adidas NMD Singapore silhouette released in the first colo ...

  2. 3.6 Templates -- Binding Element Class Names(绑定元素类名)

    1. 一个HTML元素的class属性可以像其他属性一样被绑定: <div class={{priority}}> Warning! </div> 生成的HTML <di ...

  3. Entity Framework Code First在Oracle下的伪实现(转)

    为什么要说是伪实现,因为还做不到类似MsSql中那样完全的功能.Oralce中的数据库还是要我们自己手动去创建的.这里,我们舍掉了Model First中的EDMX文件,自己在代码里面写模型与映射关系 ...

  4. 裸眼 3D 技术是什么原理?

    https://www.zhihu.com/question/19553745 作者:杨英东链接:https://www.zhihu.com/question/19553745/answer/1227 ...

  5. Sybase中的load table的用法

    Sybase中的load table的用法 用sybase iq作为数据仓库的存储,确实有其独特的特点和优势,但是在数据ETL的时候,如果用insert.update方式,速度太慢,大概是2秒钟左右一 ...

  6. ubuntu18.04系统安装+基本环境配置【原创】

    平台信息:PC:ubuntu18.04.i5.七彩虹GTX1060显卡.固态硬盘.机械硬盘 作者:庄泽彬(欢迎转载,请注明作者) 说明:在原本的电脑买一个独立显卡,装上去之后,出了各种问题,虽然后面勉 ...

  7. HDU 2848 Number Cutting Game(博弈思想 + dfs)题解

    思路:dfs找先手必胜的情况是否存在 代码: #include<stack> #include<vector> #include<queue> #include&l ...

  8. Nginx反向代理缓冲区优化

    内容目录 proxy_buffering proxy_buffer_size proxy_buffers proxy_busy_buffers_size proxy_max_temp_file_siz ...

  9. [问题解决]win10误删启动项(BCD)(HP电脑亲测,无需启动盘,并非重装系统)

    昨天使用easyBCD软件,开始不太懂,手残把win10的引导删除了,后来发现电脑关机总是变成重启,无奈强制关机.今天重启了一下电脑,发现电脑已经无法打开了,这才明白昨天是误删了win10的BCD. ...

  10. phantomjs学习资料

    http://blog.csdn.net/mecho/article/details/45888465 phantomjs的使用说明,尤其是webpage创建,资源加载前后的处理方法.