先来回顾下三次握手里面涉及到的问题:
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. Python----多元线性回归

    多元线性回归 1.多元线性回归方程和简单线性回归方程类似,不同的是由于因变量个数的增加,求取参数的个数也相应增加,推导和求取过程也不一样.. y=β0+β1x1+β2x2+ ... +βpxp+ε 对 ...

  2. keras01 - hello world ~ 搭建第一个神经网络

    import numpy as np from keras.datasets import mnist from keras.models import Sequential, Model from ...

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

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

  4. MTK刷机快捷键

    彻底关机后按住音量下键,连接电脑 无法关机的情况下按住音量上+电源键,手机黑屏后松开电源键,连接电脑,出现进度条后松开音量上键

  5. jmeter学习记录--05--Beanshell2

    学习beanshell时有不少的例子.遇到不少问题.在此记录下. 测试实例列表 A1:使用Beanshell请求作为测试请求 一个打包的Jar包,直接对其内的方法进行测试. 第一步:将接口jar包要放 ...

  6. Python网络爬虫精要

    目的 学习如何从互联网上获取数据.数据科学必须掌握的技能之一. 本文所用到的第三方库如下: requests, parsel, selenium requests负责向网页发送HTTP请求并得到响应, ...

  7. 使用c++如何实现在gRPC中传输文件

    使用c++实现gRPC远程调用框架中传输文件,proto文件如下: syntax = "proto3"; package transferfile; service Transfe ...

  8. 在vue 里使用腾讯ditu

    https://www.cnblogs.com/mrer/p/7144705.html

  9. mac 开发环境安装

    0: 安装brew : mac终端输入: /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/ ...

  10. Netty 客户端断线重连

    client 关闭后会执行 finally 代码块,可以在这里可以进行重连操作 public class NettyClient implements Runnable { private final ...