先来回顾下三次握手里面涉及到的问题:
1. 当 client 通过 connect 向 server 发出 SYN 包时,client 会维护一个 socket 等待队列,而 server 会维护一个 SYN 队列
2. 此时进入半链接的状态,如果 socket 等待队列满了,server 则会丢弃,而 client 也会由此返回 connection time out;只要是 client 没有收到 SYN+ACK,3s 之后,client 会再次发送,如果依然没有收到,9s 之后会继续发送
3. 半连接 syn 队列的长度为 max(64, /proc/sys/net/ipv4/tcp_max_syn_backlog)  决定

cat /proc/sys/net/ipv4/tcp_max_syn_backlog
3240000

4. 当 server 收到 client 的 SYN 包后,会返回 SYN, ACK 的包加以确认,client 的 TCP 协议栈会唤醒 socket 等待队列,发出 connect 调用
5. client 返回 ACK 的包后,server 会进入一个新的叫 accept 的队列,该队列的长度为 min(backlog, somaxconn),默认情况下,somaxconn 的值为 128,表示最多有 129 的 ESTAB 的连接等待 accept(),而 backlog 的值则由 int listen(int sockfd, int backlog) 中的第二个参数指定,listen 里面的 backlog 的含义请看这里。需要注意的是,一些 Linux 的发型版本可能存在对 somaxcon 错误 truncating 方式

cat /proc/sys/net/core/somaxconn
65535

6. 当 accept 队列满了之后,即使 client 继续向 server 发送 ACK 的包,也会不被相应,此时,server 通过 /proc/sys/net/ipv4/tcp_abort_on_overflow 来决定如何返回,0 表示直接丢丢弃该 ACK,1 表示发送 RST 通知 client;相应的,client 则会分别返回 read timeout 或者 connection reset by peer。上面说的只是些理论,如果服务器不及时的调用 accept(),当 queue 满了之后,服务器并不会按照理论所述,不再对 SYN 进行应答,返回 ETIMEDOUT。根据这篇文档的描述,实际情况并非如此,服务器会随机的忽略收到的 SYN,建立起来的连接数可以无限的增加,只不过客户端会遇到延时以及超时的情况。

cat /proc/sys/net/ipv4/tcp_abort_on_overflow
0

可以看到,整个 TCP stack 有如下的两个 queue:

1. 一个是 half open(syn queue) queue(max(tcp_max_syn_backlog, 64)),用来保存 SYN_SENT 以及 SYN_RECV 的信息。
2. 另外一个是 accept queue(min(somaxconn, backlog)),保存 ESTAB 的状态,但是调用 accept()。

注意,之前我对 Recv-Q/Send-Q 的理解有些误差,使用 ss 获取到的 Recv-Q/Send-Q 在 LISTEN 状态以及非 LISTEN 状态所表达的含义是不同的。从 tcp_diag.c 源码中可以看到二者的区别:

LISTEN 状态: Recv-Q 表示的当前等待服务端调用 accept 完成三次握手的 listen backlog 数值,也就是说,当客户端通过 connect() 去连接正在 listen() 的服务端时,这些连接会一直处于这个 queue 里面直到被服务端 accept();Send-Q 表示的则是最大的 listen backlog 数值,这就就是上面提到的 min(backlog, somaxconn) 的值。
其余状态: 非 LISTEN 状态之前理解的没有问题。Recv-Q 表示 receive queue 中的 bytes 数量;Send-Q 表示 send queue 中的 bytes 数值。

要理解上面总结的这些,可以参见下这两个案例(12)。

通过 "SYNs to LISTEN sockets dropped" 以及 "times the listen queue of a socket overflowed" 这两个 netstat -s 获取到的 TCP 状态,可以很快的发现系统存在的一些问题。
任何一个包含 "dropped" 或者 "overflowed" 并且数值一直居高不下的 metric 从字面含义理解来看,都不是一个好现象。

对于 Nginx 来说,backlog 的默认值为 511,这个可以通过 ss/netstat 的 Send-Q 确认:

ss -ln|egrep -i ":80"
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
tcp LISTEN 0 511 *:80 *:*

可以通过适当的增大 nginx 的 backlog 以及 somaxconn 来增大队列:

listen 80 backlog=1638

上面说了这么多,其实就是为了引入下面这个问题。
我们线上一个基于 Netty 的代码,3.5.12 的版本,监控显示 "times the listen queue of a socket overflowed" 常年居高不下,动辄几十 K,通过 ss,我们发现其 backlog 的值只有 50:
Recv-Q Send-Q           Local Address:Port               Peer Address:Port   
0      50                           *:6928                          *:*        users:(("java",454409,196))

g 了一下,发现这个版本复用了 Java 默认的 50这个值。将其增加到 1024 测试,监控曲线一下子降低到了 0。

除了上面这些,还有一个比较基础的 net.core.netdev_max_backlog,如果内核接受包的速度大于被 userspace 处理的速度,该值定义了可以在接口输入最大的的包数量。

010_TCP queue的研究的更多相关文章

  1. day39 进程

    目录 一.进程对象的其他方法 二.僵尸进程与孤儿进程(了解) 1 僵尸进程 2 孤儿进程 三.守护进程 四.互斥锁 五.进程间通信 六.IPC机制 七.生产者消费者模型 八.线程理论 一.进程对象的其 ...

  2. Python 多道技术以及进程、线程和协程

    多道技术 并发:看起来像同时运行 并行:真正意义上的同时运行,并行肯定是并发 空间的复用与时间复用 空间复用 多个程序用一套计算机硬件 时间复用 程序切换节省时间 ''' 切换(cup)分为两种情况 ...

  3. 源码之Queue

    看源码可以把python看得更透,更懂,想必也是开发人员的必经之路. 现在有个任务,写个线程池.使用Queue就能写一个最简单的,下面就来学学Queue源码. 源码之Queue: class Queu ...

  4. CWMP开源代码研究3——ACS介绍

    声明:本文涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅号:408797506) 本文介绍自己用过的ACS,其中包括开源版(提供下载包)和商业版(仅提供安装包下载 ...

  5. Unity5.x版本AssetBundle加载研究

    之前说了 “Unity5.x版本AssetBundle打包研究”,没看过的请先看一下:http://www.shihuanjue.com/?p=57 再来看本文,有一定的连接性. 先梳理一下思路: 要 ...

  6. BZOJ4241 历史研究

    Description IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. ...

  7. JAVA基础知识之Queue集合

    Queue接口 PriorityQueue类 Deque与ArrayDeque LinkedList 各种线性表性能分析 Queue接口 Queue用来模拟队列这种数据结构,遵循先进先出原则(FIFO ...

  8. Android Priority Job Queue (Job Manager)(一)

     Android Priority Job Queue (Job Manager)(一) 一.为什么要引入Android Priority Job Queue (Job Manager)?如今的A ...

  9. iOS多线程的初步研究(六)-- NSOperation

    iOS平台提供更高级的并发(异步)调用接口,让你可以集中精力去设计需完成的任务代码,避免去写与程序逻辑无关的线程生成.运行等管理代码.当然实质上是这些接口隐含生成线程和管理线程的运行,从而更加简洁地实 ...

随机推荐

  1. 菜鸟学IT-分布式版本控制系统Git的安装与使用

    分布式版本控制系统Git的安装与使用 本次作业要求来于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2103 一.首先在window ...

  2. Infiniband 网络性能测试

    1.带宽测试   在server端执行 [ibtests]# ib_send_bw -a -c UD -d mlx4_0 -i 1 ---------------------------------- ...

  3. 【刷题】牛客网看到的鹅厂ML面筋-部分问题RecSys相关

    昨天下午六点半的电话面试,其实我已经有了一个不错的实习offer ,不是特别想去腾讯了,没有太怎么准备,接的电话. 整个面试15分钟,开始就是自我介绍,接着问项目,和上一段百度实习经历.问题大致如下: ...

  4. [转帖]为应用程序池“XXX”提供服务的进程在与 Windows Process Activation Service 通信时出现严重错误。该进程 ID 为“XXXX”。数据字段包含错误号。

    [终极解决方案]为应用程序池“XXX”提供服务的进程在与 Windows Process Activation Service 通信时出现严重错误.该进程 ID 为“XXXX”.数据字段包含错误号. ...

  5. MyBatis 3源码解析(三)

    三.getMapper获取接口的代理对象 1.先调用DefaultSqlSession的getMapper方法.代码如下: @Override public <T> T getMapper ...

  6. MySQL-代码自动补全工具

    一.工具名称 mycli :  具有自动完成和语法高亮的功能 二.安装 pip install mycli 三.使用方法: mycli -u root -p password 四.效果图

  7. react 事件绑定 es5/es6

    // vscode shift + ctrl + v 预览 es 5 写法 无参函数的绑定 first methods 定义函数: handleClick(e) { // e - 事件对象 e.pre ...

  8. git几个必知托管平台

      程序员必须知道的几个Git代码托管平台 说到Git代码托管平台,首先推荐的是GitHub,好多好的开源项目都来自GitHub,但是GitHub只能新建公开的Git仓库,私有 仓库要收费,如果你做的 ...

  9. 洛谷P1122最大子树和题解

    题目 一道比较好想的树形\(DP\) 完全可以用树形DP的基本思路,递归,然后取最优的方法. \(Code\) #include <iostream> #include <cstri ...

  10. Codeforces Round #549 (Div. 1)

    今天试图用typora写题解 真开心 参考 你会发现有很多都是参考的..zblzbl Codeforces Round #549 (Div. 1) 最近脑子不行啦 需要cf来缓解一下 A. The B ...