文章插图
首先我们必须明白 , 处于“LISTENING”状态的TCP socket , 有两个独立的队列:
- SYN队列(SYN Queue)
- Accept队列(Accept Queue)
SYN队列
SYN队列存储了收到SYN包的连接(对应内核代码的结构体: struct inet_request_sock) 。它的职责是回复SYN+ACK包 , 并且在没有收到ACK包时重传 , 直到超时 。在linux下 , 重传的次数为:
$ sysctl net.ipv4.tcp_synack_retriesnet.ipv4.tcp_synack_retries = 5文档中对 tcp_synack_retries 的描述如下:
tcp_synack_retries - int整型 对于一个被动TCP连接 , 重传SYNACKs的次数 。该值不能超过255 。默认值为5 , 如果初始RTO是1秒 , 那么对应的最后一次重传是31秒 。对应的最后一次超时是63秒之后 。发送完SYN+ACK之后 , SYN队列等待从客户端发出的ACK包(也即三次握手的最后一个包) 。当收到ACK包时 , 首先找到对应的SYN队列 , 再在对应的SYN队列中检查相关的数据看是否匹配 , 如果匹配 , 内核将该连接相关的数据从SYN队列中移除 , 创建一个完整的连接(对应内核代码的结构体: struct inet_sock ) , 并将这个连接加入Accept队列 。
Accept队列
Accept队列中存放的是已建立好的连接 , 也即等待被上层应用程序取走的连接 。当进程调用accept() , 这个socket从队列中取出 , 传递给上层应用程序 。
这就是Linux处理SYN包的一个简单描述 。顺便一提 , 当socket开启了 TCP_DEFER_ACCEPT 和 TCP_FASTOPEN 时 , 工作方式将会有细微不同 , 本文不做介绍 。
队列大小限制
应用程序通过调用系统调用listen(2) , 传入backlog参数 , 来设置SYN队列和Accept队列的最大大小 。比如下面这样 , 将SYN队列和Accept队列的最大大小同时设置为1024:
listen(sfd, 1024)注意 , 在4.3版本之前的内核 , SYN队列的大小是用另一种方式计算 。
【TCP的SYN队列和Accept队列】SYN队列的最大大小以前是用 net.ipv4.tcp_max_syn_backlog 来配置 , 但是现在已经不再使用了 。现在用 net.core.somaxconn 来同时表示SYN队列和Accept队列的最大大小 。在我们的服务器上 , 我们将它设置为16k:
$ sysctl net.core.somaxconnnet.core.somaxconn = 16384队列设置为多大合适
知道了上面这些信息后 , 你可能会问 , 队列设置为多大合适?
答案是:看情况 。对于大多数的TCP服务来说 , 这并不太重要 。比如 , Go语言1.11版本之前 , 并没有提供设置队列大小的方法 。
尽管如此 , 也存在一些合理的原因 , 需要增大队列的大小:
- 当建立连接的请求速度确实很大时 , 即使是对于一个高性能的服务来说 , SYN队列也可能需要设置的大一些 。
- SYN队列的大小 , 换言之就是等待ACK包的连接数 。也即与客户端的平均往返时间越大 , 堆积在SYN队列中的连接就越多 。对于那些大部分客户端都距离服务器很远的场景 , 比如说往返时间几百毫秒以上 , 可以将队列大小设置的大一些 。
- TCP_DEFER_ACCEPT 选项如果打开了 , 会导致socket在 SYN-RECV 状态下维持更长的时间 , 也即增大了处于SYN队列中的时间 。
- SYN队列中的每一个槽位都需要占用一些内存 。当遇到SYN Flood攻击时 , 我们没有必要为这些发起攻击的包浪费资源 。SYN队列中的 inet_request_sock 结构体 , 在4.14内核下 , 每个将占用256字节的内存 。
$ ss -n state syn-recv sport = :80 | wc -l119$ ss -n state syn-recv sport = :443 | wc -l78
推荐阅读
- 暖气片清洗之后有什么需要注意的,暖气片清洗要加清洗剂吗
- 分享6 款面向Linux服务器的开源绘图应用程序
- OSI七层模型每层的作用,超详细
- 瓷砖上的肥皂垢怎么办,卫生间玻璃上的肥皂水怎么洗
- 无线路由器、AP、胖AP、瘦AP的概念区别
- 空调外机不转是压缩机坏了吗,空调外机不转是压缩机的问题吗
- McAfee杀毒软件中的提权漏洞
- 雪花秀适合多大年龄的人使用 雪花秀适合什么年龄用?全系列介绍
- 你一定要知道,关于https的五大误区
- 世界最大的淡水湖泊群 世界最大的淡水湖群是什么湖