[转帖]神秘的backlog参数与TCP连接队列

神秘,backlog,参数,tcp,连接,队列 · 浏览次数 : 0

小编点评

#Linux命令拾遗-入门篇原来awk真是神器啊Linux文本命令技巧(上)Linux文本命令技巧(下)字符编码解惑 ##Introduction Linux文本命令是用来进行各种操作的工具,它们可以用来进行文本处理、网络操作、系统操作等。 awk是文本处理工具中的一个重要工具,它可以用来进行各种文本处理操作,包括数据过滤、数据处理、网络操作等。 ## awk简介 awk是文本处理工具中的一个重要工具,它可以用来进行各种文本处理操作,包括数据过滤、数据处理、网络操作等。 awk的结构如下: ```awk #处理数据 #打印数据 ``` ## awk的基本操作 awk可以使用各种操作来进行文本处理,包括数据过滤、数据处理、网络操作等。以下是一些常用的awk操作: * `#`:注释块,可以用来存放注释,但不会执行该操作。 * ``:字符串模式,可以用来存放字符串,但会执行该操作。 * ``:匹配模式,可以用来匹配字符串,但会执行该操作。 * ``:范围模式,可以用来匹配字符串,但会执行该操作。 * `=`:赋值操作,可以用来将字符串赋值给变量。 * ``:运算符,可以用来进行各种运算。 ## awk示例 以下是一些示例展示 awk的基本操作: ```awk #过滤数据 data{ #将数据保存到变量中 var = $1; } #打印数据 print var; #使用字符串模式过滤数据 data{ #将数据保存到变量中 var = $2; } #使用范围模式过滤数据 data{ #将数据保存到变量中 var = $3; } #使用运算符进行数据处理 data{ #将数据保存到变量中 var = $1 + $2; } ``` ## awk应用 awk可以用来进行各种文本处理操作,包括数据过滤、数据处理、网络操作等。以下是一些应用 awk的例子: * **数据过滤**:可以使用awk过滤数据,将数据满足特定的条件。例如,可以使用awk过滤数据,将所有大于10的字符串保存到一个变量中。 * **数据处理**:可以使用awk进行数据处理,例如计算数据、合并数据等。例如,可以使用awk计算所有大于10的字符串的平均值。 * **网络操作**:可以使用awk进行网络操作,例如连接到服务器、发送数据等。例如,可以使用awk连接到服务器,发送数据等。 ## awk学习资源 * awk官方文档: awk 文档 * awk教程: awk教程 * awk学习资源: awk学习资源 ##总结 awk是Linux文本处理工具中的一个重要工具,它可以用来进行各种文本处理操作,包括数据过滤、数据处理、网络操作等。 awk的学习资源很多,您可以根据自己的需求进行学习。

正文

https://www.cnblogs.com/codelogs/p/16060820.html

 

原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。

简介#

这要从一次压测项目说起,那是我们公司的系统与另几家同行公司的系统做性能比拼,性能数据会直接影响项目中标,因此压力非常大。

当时甲方给大家提供了17台服务器供系统部署,并使用LoadRunner对系统进行压测,乙方有完全的服务器使用权,甲方派一个人负责压测并记录性能数据,要求压测QPS不低于4000。

项目开工#

接收到项目后,我们leader作为本项目的技术负责人,很快就为本项目指定了架构,web层使用nginx作为负载均衡,应用层使用weblogic服务器(理解为类似tomcat的东西即可)集群,数据库使用Oracle RAC集群,如下:
app_arch

看看这系统架构也挺简单的,心里想,高并发系统不过如此嘛?
billion_level_concurrency

待系统代码按照上述架构部署完毕后,我们就开始了第一轮压测。

好家伙,我们一开始压测,就发现压测机上有大量的网络报错,类似于Connection timed outRead timed out之类的网络异常。

但奇怪的是,我们登录到nginx或weblogic上观察机器情况,cpu、memory使用都不高,查看应用日志,发现日志中似乎并没有收到多少请求!
doubt
整个组内满脸的疑惑,压测请求为什么没到应用系统中来?那请求去哪了?一番讨论过后,组内没人能回答这个问题,然后就都埋头去网上搜索答案去了。

可是,经过半天的研究,大家都没有找出问题所在,包括leader也没有,中途参照网上调整过一些nginx、jvm配置啥的,都没见起啥明显效果!

请求外援#

leader见问题一时半会解决不了,于是就从众包网站上找到了一些高手,虽然需要花点钱,但问题能快速解决还是值得的。

首先第一位高手远程进来了,操作了大概10分钟后就放弃了,看来钱不好挣。
first_person
然后第二位高手远程进来了,弄了个把小时,还重新编译了nginx,最终也放弃了,问题没有解决。
second_person
然后第三位高手远程进来了,只见他进来之后,就吩咐我们开始压测,然后就是他的show time了。
third_person
只见他不断地观察着一个命令的输出结果,命令如下:

$ netstat -nat | awk '/tcp/{print $6}'|sort|uniq -c
     16 CLOSE_WAIT
     80 ESTABLISHED
      6 FIN_WAIT2
     11 LAST_ACK
      8 LISTEN
     22 SYN_RECV
    400 TIME_WAIT

观察了一会后,他就叫我们停下来,他要调整一些内核参数了,调整参数如下:

$ vi /etc/sysctl.conf
net.ipv4.tcp_max_syn_backlog = 8192
net.core.netdev_max_backlog = 8192
net.core.somaxconn = 8192
net.ipv4.ip_local_port_range = 1024 65000

net.ipv4.tcp_syn_retries = 3
net.ipv4.tcp_synack_retries = 3
net.ipv4.tcp_retries1 = 3
net.ipv4.tcp_retries2 = 5
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1

调整完毕后,我们又开始压测,效果十分明显,虽然后端系统此时也有很多报错,但至少请求都进来了!
ok_666

至此,本次压测的核心技术难题已经解决,虽然后面也调整过一些jvm参数与代码,但都在我们自己的掌控范围内,这些就不再提了。

但我当时根本就看懵了,不知道大佬弄了些啥?
what_are_you

半连接队列与全连接队列#

经过一段时间的网上搜索,我发现了新的知识点,就是TCP建立连接的过程里面,有两个队列,分别是半连接队列与全连接队列,如下:
socket_workflow

  1. 服务端要提供服务,会调用bind()listen()函数,创建一个LISTEN状态的Socket。
  2. 当客户端建立连接时,会发SYN包,即三次握手的第一步,服务端收到后,会创建一个SYN_RECV状态的Socket,放入半连接队列,并且回复SYN+ACK(即三次握手第二步)。
  3. 当客户端收到SYN+ACK后,将自己的Socket状态变更为ESTABLISHED,并给服务端回复ACK。
  4. 服务端收到ACK后,将对应半连接队列里的Socket移动到全连接队列,并将其状态变更为ESTABLISHED。
  5. 服务端accept()轮询线程这时会从全连接队列里面取到新的Socket,然后就可以使用此Socket与客户端交换数据了。

可以看到,在服务端建立连接的过程中,会经历半连接队列与全连接队列,如果半连接队列或全连接队列满了,会怎么样呢?

  1. 如果半连接队列满了,会丢弃客户端发来的SYN,而客户端如果发了几次SYN都没有收到SYN+ACK,会报Connection timed out异常,这解释了我们压测机上的大量报错。
  2. 如果全连接队列满了,会丢弃客户端回复的ACK与数据包,因为此时客户端是ESTABLISHED(连接已建立)状态,然后客户端会发具体的请求数据包,然后请求数据包一直被丢弃,会导致客户端报Software caused connection abort :socket write errorRead timed out
  3. 另外,全连接队列满了,也会导致丢弃第一次握手的SYN,这也会导致Connection timed out异常。

可见,半连接队列与全连接队列的大小非常重要,而内核默认配置都是128,这太小了!如下:

$ vi /etc/sysctl.conf
# 这是半连接队列的大小
net.ipv4.tcp_max_syn_backlog = 8192
# 这是全连接队列的大小
net.core.somaxconn = 8192

# 使得配置修改生效
$ sysctl -p

# 查看当前配置
$ sysctl -a

另外,Socket网络编程一般也可以指定一个backlog参数,如java中的ServerSocket:

int port=8080;
int backlog=8192;
ServerSocket ss = new ServerSocket(port, backlog);
while(true){
  //接收到新连接
  Socket s = ss.accept();

  new Thread(()->{
    //socket读写操作...
  }, "socket-thread-" + s).start();
}

这个backlog参数,就是配置全连接队列的大小的,但全连接队列大小实际由内核与应用程序同时决定,取net.core.somaxconn与应用中backlog的最小值。

所以,一般网络服务程序(tomcat、redis、mysql等)都会有一个backlog的配置,在springboot内置的tomcat中,backlog配置方法如下:

server:
  port: 8080
  tomcat:
    accept-count: 8192   # 内置tomcat的全连接队列大小配置

观测TCP连接队列#

如上,大佬当时诊断问题时,主要使用的是netstat命令,用于统计各状态Socket的数量,如下:

$ netstat -nat | awk '/tcp/{print $6}'|sort|uniq -c
     16 CLOSE_WAIT
     80 ESTABLISHED
      6 FIN_WAIT2
     11 LAST_ACK
      8 LISTEN
     22 SYN_RECV
    400 TIME_WAIT

从这里可以看到,ESTABLISHED状态的Socket数量较少,大佬估计是觉得压测时正常连接不应该这么少,然后就认定是TCP连接队列大小配置有问题,导致压测QPS上不去。

当然,这是非常依赖经验的,因为这个数据并不直观,估计大佬有多年的性能优化经验,才能感觉到这个连接数是不正常的。

经过我多方搜索,我发现有一些方法,可以直接观测到连接队列的使用情况。

  1. 观测连接队列长度
# ss命令对于LISTEN状态的Socket
# Recv-Q是全连接队列的当前大小
# Send-Q是全连接队列的最大值
$ ss -nltp
State      Recv-Q       Send-Q          Local Address:Port            Peer Address:Port          Process
LISTEN     0            10                    0.0.0.0:8080                 0.0.0.0:*              users:(("ncat",pid=25760,fd=3))

# netstat命令对于LISTEN状态的Socket
# Recv-Q是半连接队列的当前大小
# Send-Q一般显示为0
$ netstat -nltp
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      25760/ncat

可见,通过ss或netstat命令,可以直接观测到TCP连接队列的大小,另外,也有办法观测到由于队列溢出而丢弃包的次数,如下:

  1. 观测连接队列溢出而丢弃包的次数
$ netstat -s|grep -iE LISTEN
  52 times the listen queue of a socket overflowed    # backlog满了,溢出的次数  
  52 SYNs to LISTEN sockets ignored                   # SYN包drop的次数

从上可以看到,SYN被drop了52次,可能是连接队列设置过小导致。

ss其它用法#

一般做过网络编程的话,应该了解过,每个socket都可以设置recv buffer(读缓冲)和send buffer(写缓冲),而对于ESTABLISHED状态的socket,ss命令可以观测到这两个buffer的使用情况,如下:

  • Recv-Q:表示的是recv buffer中用户进程未来得及read()走的数据大小。
  • Send-Q:表示的是write()到send buffer中远程主机还未返回ACK确认包的数据大小。

一般来说,这两个buffer内核可自动调整大小,并不需要我们手动配置,另外,使用netstat还可以观测到这两个buffer不足导致的丢包情况,如下:

$ netstat -s|grep -E 'pruned|collapsed'
  19963 packets pruned from receive queue because of socket buffer overrun
  665 packets collapsed in receive queue due to low socket buffer
  • collapsed:由于tcp包的header部分内容有很多是一样的,Linux为了节省Tcp header所占用的内存,使相同header的tcp包复用同一个header以节省内存,当socket的recv buffer不足时,会触发这个行为。
  • pruned:是指内核在collapsed时的尝试后,仍未有足够空间接收包则此时直接丢包。

总结#

这次压测给我的印象很深,发现了在Java的世界外面,还有很多的底层机制运行着,它们一般不出问题,但一旦出现问题,将是非常难以定位的问题,这也促使我后面花了大量时间去补Linux和网络相关的知识点。

另外,其实TCP连接队列相关知识点,在运维圈子里会分享的更多,因为他们经常部署系统、部署软件嘛,时间久了自然会了解到,这也促使我后面越来越多的关注到运维与DBA层面的知识点。

往期内容#

Linux命令拾遗-入门篇
原来awk真是神器啊
Linux文本命令技巧(上)
Linux文本命令技巧(下)
字符编码解惑

与[转帖]神秘的backlog参数与TCP连接队列相似的内容:

[转帖]神秘的backlog参数与TCP连接队列

https://www.cnblogs.com/codelogs/p/16060820.html 原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 简介# 这要从一次压测项目说起,那是我们公司的系统与另几家同行公司的系统做性能比拼,性能数据会直接影响项目中标,因此压力非

[转帖]神秘的backlog参数与TCP连接队列

https://www.cnblogs.com/codelogs/p/16060820.html 简介# 这要从一次压测项目说起,那是我们公司的系统与另几家同行公司的系统做性能比拼,性能数据会直接影响项目中标,因此压力非常大。 当时甲方给大家提供了17台服务器供系统部署,并使用LoadRunner对

[转帖]TCP的blacklog之全连接队列与半连接队列的深入研究

文章目录 Linux内核探测工具systemtap的安装与使用backlog、半连接队列、全连接队列是什么半连接队列、全连接队列基本概念 linux 内核是如何计算半连接队列、全连接队列的半连接队列的大小的计算模拟半连接队列占满全连接队列(Accept Queue) SYN+ACK重传次数全连接队列

[转帖]把大象装入货柜里——Java容器内存拆解

https://blog.mygraphql.com/zh/notes/java/native-mem/java-native-mem-case/ 介绍 测试环境 配置容量 POD 容量配置 JVM 容量配置 神秘的 MaxDirectMemorySize 默认值 maxThreadCount 最大

[转帖]JVM 中你不可不知的参数

https://zhuanlan.zhihu.com/p/91757020?utm_id=0 有的同学虽然写了一段时间 Java 了,但是对于 JVM 却不太关注。有的同学说,参数都是团队规定好的,部署的时候也不用我动手,关注它有什么用,而且,JVM 这东西,听上去就感觉很神秘很高深的样子,还是算了

[转帖]申威-揭秘中国军方神秘全自主芯片!

http://www.ichyang.com/post/2358.html 相对于从诞生之初就处于舆论风口浪尖的“龙芯”,中国另一款走全自主道路的芯片“申威”,相比之下就低调得多。陆媒近日刊文试图揭秘这款由军方秘密开发的全自主芯片。 无论是传统纸媒还是网络媒体,“申威”的曝光率比起“龙芯”、“海思”

【转帖】【性能提升神器】STRAIGHT_JOIN

今天给大家下另一个性能提升神器-STRAIGHT_JOIN,在数据量大的联表查询中灵活运用的话,能大大缩短查询时间。 首先来解释下STRAIGHT_JOIN到底是用做什么的: STRAIGHT_JOIN is similar to JOIN, except that the left table i

[转帖]什么是光纤?光纤的原理是什么?你能想象没有光纤通讯的世界么?

什么是光纤? 大量的光纤 光纤是光导纤维,是一种由玻璃或塑料制成的纤维,利用光在这些纤维中以全内反射原理传输的光传导工具 光纤有什么特点呢? 光纤如果封装在塑料保护套中,它就能够弯曲,也不会断裂,是一种极佳的信号传递工具光纤在传输过程中的损耗比电在电线中的损耗,要低很多,现在较好的光导纤维,其光传输

[转帖]什么是 istio

https://cizixs.com/2018/08/26/what-is-istio/ 如果你比较关注新兴技术的话,那么很可能在不同的地方听说过 istio,并且知道它和 service mesh 有着牵扯。这篇文章是我之前在公司内部做过的分享,可以作为了解 istio 的入门介绍,了解什么是 i

【转帖】读懂什么是RDMA

一.什么是RDMA 1.RDMA主要体现 2.如何理解RDMA和TCP技术的区别? 3.使用RDMA的好处包括: 二.什么是RoCE? 1. RDMA协议包含: Infiniband(IB) 2. 为什么RoCE是目前主流的RDMA协议? RoCEv1 RoCEv2 RoCE,无损先行 一.什么是R