缘起

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

我现在负责的服务器是一台接口服务器,所有的卖家都要通过这台服务器连接到自己的数据库上,不得小觑。于是我立马放下手头的话,打开了我事先安装好的服务器监控软件(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的更多相关文章

  1. 线上服务器TCP被打满是啥情况

    从一个线上服务器警告谈谈backlog https://wangxiangnan.cc/?p=105 缘起 双十一如期而至,此时的我因为在处理客户的一个问题已经陷入了忙碌.突然,不断接到驻场实施发来的 ...

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

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

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

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

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

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

  5. 01 . Go之Gin+Vue开发一个线上外卖应用

    项目介绍 我们将开始使用Gin框架开发一个api项目,我们起名为:云餐厅.如同饿了么,美团外卖等生活服务类应用一样,云餐厅是一个线上的外卖应用,应用的用户可以在线浏览商家,商品并下单. 该项目分为客户 ...

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

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

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

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

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

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

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

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

随机推荐

  1. 报表技术之PDF格式报表生成 ----JasperResport

    JasperReport简介 JasperReport:java提供的一个类库,承上启下,读取IReport生成的xxx.jrxml文件,获取到pdf中需要显示的全部内容,然后底层调用IText相关的 ...

  2. 【遥感专题系列】微波遥感(二、合成孔径雷达SAR基础)

    目前使用最广的成像雷达系统就是合成孔径雷达(Synthetic Aperture Radar:SAR),SAR几乎成为了雷达的代名词.本文从应用角度介绍SAR系统的基本知识. 本文主要包括: SAR基 ...

  3. Storm 中drpc调用

    package storm.starter; import backtype.storm.Config; import backtype.storm.LocalCluster; import back ...

  4. 表达式过滤器 uppercase

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  5. Anaconda的使用—Spyder常用快捷键

    Ctrl + 1: 注释/反注释 Ctrl + 4/5: 块注释/块反注释 Ctrl + L: 跳转到行号 Tab/Shift + Tab: 代码缩进/反缩进 Ctrl +I:显示帮助

  6. Java跨系统调用接口(POST)

    package com.bing.util; import com.bing.constant.ResultModel; import com.bing.model.Company; import c ...

  7. jzoj100029. 【NOIP2017提高A组模拟7.8】陪审团(贪心,排序)

    Description 陪审团制度历来是司法研究中的一个热议话题,由于陪审团的成员组成会对案件最终的结果产生巨大的影响,诉讼双方往往围绕陪审团由哪些人组成这一议题激烈争夺. 小 W 提出了一个甲乙双方 ...

  8. vim删除文件所有内容

    在命令模式下,输入:.,$d 回车.

  9. IDEA的使用方法(三)(改变字体主题)

    今天正式写代码的时候发现,一开始由于破解的太随意,没有设定好主题和字体现在看的有点昏,那么接下来就发一个该如何改变IDEA的字体和主题的教程: File——>setting——>Edito ...

  10. JSP/Servlet开发——第一章 动态网页基础

    1.动态网页:在服务端运行的使用程序语言设计的交互网页 : ●动态网站并不是指具有动画功能的网站,而是指网站内容可根据不同情况动态变更的网站(股票网站),一般情况下动态网站通过数据库进行架构. ●动态 ...