Nginx: TCP建立连接的优化和启用Fast Open功能

TCP 建立连接优化

  • 在三次握手中,相关TCP的内核参数可优化这一过程
    • net.ipv4.tcp_syn_retries = 6
    • net.ipv4.tcp_synack_retries = 5
    • net.ipv4.tcp_syncookies = 0
    • net.ipv4.tcp_max_syn_backlog
    • net.core.somaxconn
    • net.core.netdev_max_backlog

1 ) net.ipv4.tcp_syn_retries = 6

  • 上面,一个是 syn,一个是 synack,对应TCP的两个不同的阶段
  • Nginx 是一个中间服务器,下游服务器有这个客户端,它的上游服务器有应用程序服务器
  • 假如,Nginx服务器想要作为客户端去请求上游应用程序服务器的数据的时候
  • Nginx 也需要向客户端一样发送一个SYN的请求包给后端的应用程序服务器建立这个TCP连接
  • Nginx 客户端在发送完这样一个SYN之后,有可能因为网络的原因导致后端的应用程序服务器
  • 没有及时返回SYN加ACK的响应包给 Nginx 的时候,Nginx自身会再次发送这样一个SYN的包
  • TCP是有超时重传这样一个机制的, 因此这个参数其实就是用来决定Nginx和上游服务器交互的时候它
  • 也就是跟上游服务器请求建立TCP连接的时候,首次发送SYN包这个重试次数
  • 也就说Nginx第一次发送失败之后,会间隔一定的时间之后再去发送一次SYN包
  • 如果说超过了这样一个次数之后,还是没有正确建立TCP连接,这个时候就会放弃
  • 假如说,现在的Nginx服务器是一个高负载的服务器,想要去优化这样一个过程
  • 通常跟后端的服务器来说,6 这个数值可能会有些偏大,通常需要调低到2或3

2 )net.ipv4.tcp_synack_retries = 5

  • 还有一个叫 tcp_synack_retries 在Nginx上去修改这样一个参数的话
  • 它影响的是Nginx作为服务器的时候(对应用户的客户端,发一个请求到Nginx的时候)
  • 客户端会发送给Nginx一个SYN的包,Nginx 会回送一个SYN加ACK的确认包
  • 这个时候,假如说客户端不响应,最后一个ACK给我的时候,我会重试
  • 这里5 并不是一个次数大概就是 180 秒,可以修改短一些,每个1大概 180 / 5 = 3x s
  • 修改成2,就成了70s左右,这个参数影响的是Nginx服务器和应用程序服务器之间的一个连接
  • 如果自己内部网络很好的话,可以把这个参数调小
  • 对于Nginx高并发这样的一种服务器,必须让每一个细节尽可能的时间变少
  • 在连接非常多的情形下,每一个点去耗费一些时间,整体性能会急剧的下降
  • 上面两个参数是Nginx作为客户端的一个参数,下面这个参数是Nginx作为服务器端的一个参数

3 )net.ipv4.tcp_syncookies = 0

  • 默认在linux中配的是0,很多现在的一些linux服务器可能会把这个参数置为 1 了
  • 它是为了应对 syn flood 攻击的
  • 在之前TCP协议还不规范的时候,客户端可以通过一定的工具伪造很多不同IP的 syn 包
  • 它们去向服务器发起 syn 请求, 去建立TCP连接, 这些过多的伪造包到达 Nginx 服务网卡
  • 网卡收到这些 syn 包之后,就会递给 syn 队列,这样,syn队列很快被打满
  • 同时,伪造的包,ip很多也是伪造的,不存在的,Nginx会送请求后是不能得到响应ACK的
  • 这样,所有伪造的包伪造的 syn 在队列中不释放,新的连接无法进入服务器,正常请求无法处理
  • syn flood 攻击是最早TCP/IP设计不规范时候出现的,为了避免这种场景出现,则设计了这个参数
  • 客户端发送SYN的时候,服务器收到这个SYN包之后,就会立即在服务器中的给它开辟一些内存空间来存放这个连接中的一些信息
  • 这个连接过来之后,服务器就立马去分配存储空间的话,假如说客户端是一个黑客
  • 他们用工具模拟了很多 syn 包发送到 服务器端,服务器针对每一个连接都去分配一个存储空间
  • 对我服务器影响性能是非常大的, 为了避免这种情形的话,当我的客户端在发送 syn 包给服务器的时候不会立即给你分配的一个存储空间
  • 服务端会通过一定的算法计算出一个cookie,之后,把 SYN 包加ACK,发送给客户端
  • 假如说, 客户端能够正确回送ACK的时候, 那就代表这个客户端是一个真实存在的客户端
  • 验证客户端发过来的ACK这个报文中可能带有的cookie信息的真伪
  • 假如,这个表中的cookie返回是一样的,再给客户端去分配这样一个存储空间,这个时候就验证了
  • 假如说第一次,比如说你黑客发送了很多的syn包到我的服务器
  • 没关系,服务器不会直接给你分配存储空间,既然不涉及在内存中分配存储空间
  • 也就意味着,整个服务器不会被立马打死,这时候会送很多 SYN加ACK, 包含计算出的cookie
  • 伪造IP的 syn 包,是无法正常回送 ACK包到服务器的,因此避免了 syn 的攻击
  • tcp_syncookies = 0 表示这个功能没有打开,置为 1 则表示开启,在centos7之后,就默认为1了

4 )net.ipv4.tcp_max_syn_backlog

  • 换一种角度看我们客户端和我的这个服务器,建立三次握手的中间的一些细节
  • 客户端发送一个SYN的包到 Nginx 服务器上
  • Nginx 服务器拿到之后,它内核的TCP/IP协议栈会处理这样一个数据包
  • 这个数据包会被它放到SYN队列里边,这个队列长度很小的话,必然会影响整个Nginx的并发数量
  • 通常情况下,会把这样一个队列的长度调大,由这个内核参数决定:tcp_max_syn_backlog
  • 当这个连接到SYN队列之后,这个Nginx服务器的TCP/IP协议栈,会回送一个SYN加ACK的包给客户端
  • 之后,假如说客户端正确的回送了ACK给Nginx服务器,内核中的TCP/IP协议栈拿到之后
  • 它会在这个SYN队列中找到对应客户端的一个连接,会把这个连接从队列中剔除掉
  • 同时它会把这个连接放到accept队列,表示这个连接已经正确的建立了,三次握手已经完成了
  • 接下来需要有上层的应用层的应用进程来处理。比如accept的队列需要对应上面的应用程序进程是80
  • 也就是这个时候Nginx可以到这个对应的队列中去找到这个TCP连接,进行处理
  • Nginx进程的accept队列它有多大呢? 通过这样一个参数:listen :80 backlog=248000;
  • 这个 backlog=248000 就是 accept 队列的长度
  • 在整个linux服务器中,作为一个服务器,上面不只有Nginx进程,可能还有很多其他的进程
  • 如果其他的应用程序也需要通过TCP协议来进行处理的话, 其他应用程序也应该有 accept 队列
  • 所以,在我们的系统中,还有一个决定系统级的这个accept队列长度的一个内核参数值
  • Nginx 是通过在listen指令后面加 backlog 这样一个参数来决定 accept 队列的长度的
  • 如果 Nginx 的 accept队列很大,但是整个系统级的 accept 队列定义的很小也没用
  • 所以说还对应的需要去优化整个系统级的accept队列的长度,如果服务器只跑一个Nginx服务
  • 那可以把整个系统级的这个accept队列指定和Nginx这个backlock队列指定一样
  • 也就是尽可能让Nginx 去使用整个系统的 backlog accept队列,从而尽可能的压榨服务器的性能

5 ) net.core.somaxconn

  • 这个参数是用来指定整个系统的 accept 队列,也就是能够正确建立完TCP连接的一个队列长度
  • 因此,Nginx的 accept 的 backlog 值尽可能接近上面这个参数值

6 )net.core.netdev_max_backlog

  • 字面意思,网络设备最大的队列长度,网络设备指代我们的网卡
  • 很多连接数据已经到达了网卡,但是一部分连接已经发送给SYN队列了
  • 但是还有一部分并没有,这里就是在网卡上滞留的一些数据,通常情况下也要把它给改大一些

7 )综合配置

  • $ cat /proc/sys/net/core/netdev_max_backlog

    1000
    
  • $ cat /proc/sys/net/ipv4/tcp_max_syn_backlog

    128
    
  • $ cat /proc/sys/net/core/somaxconn

    128
    
  • 以上都是默认值,看起来值比较小,如果要更改,不能直接更改上述配置文件

  • 因为 /proc 下都是临时文件,改了临时文件会立即生效,但是重启后就变回去了

  • 通过这个命令,查看系统内核参数 $ sysctl -a | grep somaxconn

    net.core.somaxconn=128
    sysctl:readingkey "net.ipv6.conf.all.stable secret"
    sysctl:reading key "net.ipv6.conf.default.stable secret"
    sysctl:readingkey"net.ipv6.conf.ens33.stablesecret"
    sysctl:readingkey"net.ipv6.conf.ens37.stable secret"
    sysctl:readingkey "net.ipv6.conf.ens38.stable secret"
    sysctl:reading key "net.ipv6.conf.lo.stable secret"
    
  • 我们现在可以修改 $ vim /etc/sysctl.conf

    net.core.somaxconn = 8000
    net.core.netdevmaxbacklog = 248000
    net.ipv4.tcp_max_syn_backlog = 248000
    net.ipv4.tcp_syn_retries = 1
    net.ipv4.tcp synack_retries = 1
    
  • 让其生效,$ sysctl -p 生效

    net.core.somaxconn=65535     # 注意这个是最大值,不能超过这个值
    net.core.netdev_max_backlog = 248000
    net.ipv4.tcp_max_syn_backlog = 248000
    net.ipv4.tcp_syn_retries = 1
    net.ipv4.tcp_synack_retries = 1
    
  • 检查配置是否生效,$ sysctl -a | grep tcp_max_syn_backlog

    sysctl:readingkey "net.ipv6.conf.all.stable_secret"
    net.ipv4.tcp_max_syn_backlog = 248000
    sysctl:readingkey "net.ipv6.conf.default.stable_secret"
    sysctl:readingkey"net.ipv6.conf.ens33.stable_secret"
    sysctl:readingkey"net.ipv6.conf.ens37.stable_secret"
    sysctl:readingkey"net.ipv6.conf.ens38.stable_secret"
    sysctl:reading key "net.ipv6.conf.lo.stable_secret"
    
    • 发现已生效
    • 其他参数,也可以类似进行验证,此处不再赘述
  • 现在,我们可以去修改 nginx 的 backlog 队列

    server {listen 443 ssl deferred backlog=248000; # 注意这里,大于 65535 即可,不会受限于系统# ... 其他
    }
    

启用TCP的Fast Open功能


1 ) TCP 的 Fast Open

  • TCP Fast Open(TFO) 是用来加速连续TCP连接的数据交互的TCP协议扩展
  • 由Google于2011年的论文提出并实现

1.1 最初RFC中实现 TCP 协议的状态如下

  • 最初实现的是客户端发送SYN,服务端收到 SYN 包值以后回送SYN + ACK
  • 客户端收到SYN加ACK包之后,还要回送给客户端 ACK
  • 三次握手建立完连接之后,客户端就可以向服务端发送请求资源了
  • 服务端在收到这样一个请求之后,会构建响应报文,再把数据返回给我的客户端
  • RFC 在演进的时候,优化了这一过程

1.2 RFC 优化的过程

  • 当客户端第一次发送 SYN 之后,服务端回给客户端 SYN加ACK
  • 在最后一次, 客户端回送ACK的时候,在这个ACK包中直接加一些 DATA 数据
  • 比如说, 通过HTTP的get方法去请求某一个资源
  • 之前是客户端 把ACK 这个包是单独发送给服务端之后,客户端建立连接之后,再去发送请求数据包
  • 这个优化,就是少了这样一个过程,优化了一步,在大并发中,性能提升明显

1.3 2011年 Google 提出的TFO的优化

  • 当客户端发送一个 SYN 给服务端的时候,当服务器收到 SYN 包之后
  • 它会通过一定的算法, 比如根据客户端的信息,去计算出来一个cookie
  • 之后,服务端会发送SYN加ACK加cookie给客户端
  • 客户端就拿到这样一个cookie 并保存起来
  • 客户端再次最后发送 ACK 的时候,也把请求数据带上,即直接发请求(基于RFC的优化)
  • 之后就是一些数据交互了,经过一段时间之后,客户端断开连接了
  • 后面客户端又想请求数据的时候,在前面没有TFO的情形下,还是继续要发送SYN
  • 也就是说,不可避免的重复建立TCP的连接,每一次都需要三次握手过程
  • 其实,当有了TFO之后,客户端保存的cookies, 就不需要三次握手了,直接通过
  • SYN+Cookie+Data的形式与服务端通信,如上图所示
  • 服务端验证一致后,直接构建报文返回客户端DATA
  • 当服务端打开这样一个 TFO 功能,客户端也要支持这样的 TFO 功能才能生效
  • 在实际生产中,打开 TFO 功能也是极大提高吞吐性能

2 )实际环境开启 Fast Open

  • 先看一下这个核心参数 $ sysctl -a | grep tcp_fast
    sysctl:readingkey"net.ipv6.conf.all.stable_secret"
    net.ipv4.tcp_fastopen = 0
    net.ipv4.tcp_fastopen_key=00000000-00000000-00000000-00000000
    sysctl:reading key "net.ipv6.conf.default.stable_secret"
    sysctl:readingkey"net.ipv6.conf.ens33.stable_secret"
    sysctl:readingkey"net.ipv6.conf.ens37.stable_secret"
    sysctl:readingkey"net.ipv6.conf.ens38.stable_secret"
    sysctl:reading key "net.ipv6.conf.lo.stable_secret"
    
    • 这里有一个叫做:net.ipv4.tcp_fastopen 的内核参数
    • 默认为 0 意思是关闭这个TFO功能,这个值的范围是 0, 1, 2, 3
    • 1 代表,Nginx 作为客户端来说开启 TFO 的功能 (nginx 和 上游应用服务器之间)
    • 2 代表,Nginx 作为服务端来说开启 TFO 的功能,这时不管上游服务器是否开启,没用
    • 3 代表,Nginx 不论作为服务端还是客户端都开启这个 TFO 功能
  • 现在,我们写进去 $ vim /etc/sysctl.conf
    net.ipv4.tcp_fastopen  =  3  # 添加这一行进去
    
  • 验证下,$ sysctl -p
    # ... 其他
    net.ipv4.tcp_fastopen  =  3  # 可以看到,这里有了
    
  • 再次验证, $ sysctl -a | grep fast 可见下面已经打开这个功能了
    net.core.default_qdisc=pfifo_fast
    sysctl:readingkey "net.ipv6.conf.all.stable_secret"
    net.ipv4.tcp_fastopen = 3
    net.ipv4.tcp_fastopen_key=00000000-00000000-00000000-00000000
    sysctl:readingkey "net.ipv6.conf.default.stable_secret"
    sysctl:readingkey "net.ipv6.conf.ens33.stable_secret"
    sysctl:readingkey"net.ipv6.conf.ens37.stable_secret"
    sysctl:readingkey"net.ipv6.conf.ens38.stable_secret"
    sysctl:readingkey "net.ipv6.conf.lo.stable_secret"
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/878476.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

书生大模型实战营(1)——InterStudio基础知识+Vscode SSH连接远程服务器+Linux基础指令

参加书生.浦江大模型实战训练营,学习大模型知识和微调技术,所有课程免费,通过闯关的形式学习,也比较有趣。一起来了解LLM的世界。邀请链接 产品简介 InternStudio 是大模型时代下的云端算力平台。基于 InternLM 组织下的诸多算法…

小程序全局挂载对像

1. 定义并导出 `utils` 模块 // utils.js const utils = {/*** 用户消息反馈* @param {string} title 文字提示的内容*/toast(title = 数据加载失败...) {wx.showToast({title,mask: true,icon: none,});} }// 挂载到全局对象 wx wx.utils = utils;// 模块导出 export default…

使用 FormCreate 渲染 Element Plus 表单

使用 FormCreate 渲染 Element Plus 表单 FormCreate 支持多个主流 UI 框架,您可以根据自己项目的需求选择对应的版本进行安装。 请根据您项目中使用的 UI 框架,安装对应的 FormCreate 版本。 Vant UI 版本 移动端 npm i form-create/vant^3Element Pl…

高级java每日一道面试题-2024年9月01日-基础篇-事物的隔离级别?

如果有遗漏,评论区告诉我进行补充 面试官: 事物的隔离级别? 我回答: 事务的隔离级别是一个重要的考点。事务的隔离级别决定了一个事务在访问数据库时如何受到其他事务的影响,以及不同事务之间的并发控制程度。下面将详细解释Java中事务的隔离级别。 事务的隔离…

【工控】线扫相机小结 第二篇

背景 上一篇中《线扫相机小结》中介绍了一些基础知识和注意事项,这一篇是对上一篇的进一步补充。 会介绍线扫相机的一些调试技巧。 如何在线调试? 我们知道,线扫相机不能像面阵相机一样实时的呈现图像,只能一行行的扫描&#x…

HX711—称重模块

1、简介 HX711 采用了海芯科技集成电路专利技术, 是一款专为高精度电子秤而设计的 24 位 A/D 转 换器芯片。 2、原理图 PCB参考设计原理图 3、模块驱动代码(固件库) 数据读取代码分析 HX711信号读取时序 初始化: 将 PD_SCK&…

COCO数据集缺失文件补全方法

COCO2017数据集图片文件缺失自动补全方法 一、前言 本文代码是以目标检测(object detection)和实例分割(instance segmentation)任务的标签文件为例,即instances_train/val/test2017.json文件。 其他任务的标签文件…

原生冻结进程分析(U)

一、概要 1.定义: 当应用切换到后台并且没有其他活动时,系统会在一定时间内通过状态判断,将进程 ID 迁移到冻结的 cgroup 节点上,实现冻结 CACHE 应用。这项功能可以减少活跃缓存应用在后台存在时所消耗的 CPU 资源,从…

armv8 memory model概述

概述 在armv8 架构中,它引入了更多的维度来描述内存模型,从而在此基础上进行硬件优化(但其中一些并未被主流的软件所接受),在此做一些简单的整理,更多信息请参考 Arm spec 以及 AMBA 协议。下文主要是对Memory 和 Device 两大类的…

getopts(1) builtin command

文章目录 0.背景1.简介2.格式3.选项4.返回值5.特殊变量6.示例参考文献 0.背景 在执行 Shell 脚本时,可以像运行应用程序一样传入相应的参数,在脚本内部根据传入的参数内容执行对应的操作。 Shell 脚本中可以通过$1...$N形式的符号来引用传入的参数&…

基于nodejs+vue+uniapp的摄影竞赛小程序

开发语言:Nodejs框架:expressuniapp数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:VS Code 系统展示 管理员登录 管理员主界面 用户管理 书籍分类管理 书籍信息管理 系统管理…

昇腾AI处理器的计算核心 - AI Core即DaVinci Core

昇腾AI处理器的计算核心 - AI Core即DaVinci Core flyfish 从一段代码的解释开始 template <typename T> class GlobalTensor { public:void setGlobalBuffer(T* buffer, uint32_t buffersize) {// 在这里实现设置全局缓冲区的逻辑} };语法的说明&#xff0c;主要用于…

fl studio 21/24破解版(水果音乐制作软件24) v24.1.1.4285附安装教程

fl studio 21/24破解版&#xff0c;又被国内网友称之为水果音乐制作软件24&#xff0c;是Image-Line公司成立26周年而发布的一个版本&#xff0c;是目前互联网上最优秀的完整的软件音乐制作环境或数字音频工作站&#xff0c;包含了编排&#xff0c;录制&#xff0c;编辑&#x…

在Ubuntu 20.04上安装MySQL的方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 简介 MySQL 是一个开源的数据库管理系统&#xff0c;通常作为流行的 LAMP&#xff08;Linux、Apache、MySQL、PHP/Python/Perl&#xf…

Cmake之1.0版本重要特性及用法实例(八)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

GoodSync Business - 企业级服务器同步与备份工具

现在越来越多公司会搭建服务器&#xff0c;或自建文件共享中心。那么如何才能实现对这些终端的高效管理、安全备份&#xff0c;以保障企业数据的安全呢&#xff1f; GoodSync Business 就是一款企业服务器同步与备份工具&#xff0c;适用于 Win / Mac 工作站&#xff0c;以及 …

Kafka【二】关于消费者组(Consumer Group)、分区(partition)和副本(replica)的理解

【1】概述 Apache Kafka 是一个分布式流处理平台&#xff0c;它允许你发布和订阅记录流&#xff0c;存储记录流&#xff0c;并且可以对这些记录流进行处理。在 Kafka 中&#xff0c;消息被发布到特定的主题&#xff08;topic&#xff09;&#xff0c;然后由消费者&#xff08;…

57-java csrf防御方案

CSRF&#xff08;跨站请求伪造&#xff09;是一种攻击手段&#xff0c;它迫使已登录用户的web应用在没有用户知情的情况下&#xff0c;发送未经授权的请求。在Java中&#xff0c;有多种方法可以用来防御CSRF攻击。 使用同步令牌&#xff08;Token&#xff09;&#xff1a; 同…

Datawhale X 李宏毅苹果书 AI夏令营 Task2打卡

线性模型&#xff08;Linear model&#xff09; 通常模型的修改来自于对问题的理解&#xff0c;即领域知识 基本定义&#xff1a;把输入特征x乘上一个权重&#xff0c;再加上一个偏置就可以得到预测的结果。 优点&#xff1a;简单易理解&#xff0c;可理解性好&#xff08;权重…

C++可调用对象

C11中有一个重要的概念&#xff0c;叫可调用对象&#xff0c; 可调用对象用途广泛&#xff0c;比如作为线程的执行对象&#xff0c;或者在使用一些基于范围的模版函数时&#xff08; sort()、all_of()、find_if()&#xff09;&#xff0c;常常需要我们传入一个可调用对象&…