写点什么

Nginx 高并发调优中常被忽略的参数

发布于: 2021 年 05 月 20 日

在 nginx 或 php-fpm 优化的时候,经常会碰到一个参数:backlog


backlog 是什么?


在 nginx 官方文档中定义如下:



在 php-fpm 中解释如下:



从上面的解释来看,就是定义了一个队列,并设置了队列长度,那么这个队列是做什么的,接着往下看


不管是 nginx 还是 php-fpm 中 backlog 配置的地方都是在 listen 指令的位置,为什么是在 listen 指令的位置配置,通过一张图来看下



我们知道,listen 是用来创建一个监听,打开一个端口、文件描述符,用于等待客户端请求,上面这张图是 TCP 内核的请求过程


  • client 发送 SYN 到 server,将状态修改为 SYN_SEND,如果 server 收到请求,则将状态修改为 SYN_RCVD,并把该请求放到 syns queue 队列中

  • server 回复 SYN+ACK 给 client,如果 client 收到请求,则将状态修改为 ESTABLISHED,并发送 ACK 给 server

  • server 收到 ACK,将状态修改为 ESTABLISHED,并把该请求从 syns queue 中放到 accept queue


上面过程中的状态看着是不是很熟悉,我们通常在服务器上通过 ss 或 netstat 查看端口状态的时候,其实就是 TCP 连接状态


而 syns queue 和 accept queue 是由操作系统内核维护的两个队列



在操作系统中这两个队列分别由两个内核参数定义



就是上图中的 net.core.somaxconn 和 net.ipv4.tcp_max_syn_backlog

这两个参数也是通常你看到的优化 nginx 文章中推荐要设置的两个参数,如上图,net.ipv4.tcp_max_syn_backlog 参数决定了 SYN_RECV 状态队列也就是 syns queue 队列的长度,一般默认值为 512 或 1024,根据服务器内存,可以通过/proc/sys/net/ipv4/tcp_max_syn_backlog 查看,超过这个数量,系统将不再接受新的 TCP 连接请求,这里说明下,不再接受新的请求,但是不会发送 reset 等,而是对 SYN 包不再响应 SYN/ACK 包,通常只是丢弃 SYN 包,这种设计方法就比较优雅,不返回 RST,客户端可以进行重试,在内核中同样也有参数配置,通过 net.ipv4.tcp_syn_retries 参数可以配置 SYN 重试次数,这样在队列腾出空闲位置时,客户端可以重新建立连接,而不是直接被 reset


但是这个参数的生效和 tcp_syncookies 又有一定的联系,在 linux 的系统调用的 man 文档中



在 syncookies 启用的情况下,逻辑上没有最大值限制,这个设置被忽略,syncookies 通常被开启,用于防止 SYN Flood 攻击


简单说一下 syncookies,syncookies 设计就是用来防止 SYN Flood 攻击的,它的原理是,在 TCP 服务器接收到 TCP SYN 包并返回 TCP SYN+ACK 包时,不分配一个专门的数据区,而是根据这个 SYN 包计算出一个 cookie 值,这个 cookie 作为将要返回的 SYN ACK 包的初始序列号,当客户端返回一个 ACK 包时,根据包头信息计算 cookie,与返回的确认序列号(初始序列号+1)进行对比,如果相同,则时一个正常连接,然后分配资源,建立连接


扯远了,接着说另外一个参数 net.core.somaxconn,该参数决定了 listen 监听队列的大小,也就是 accept queue 队列的大小。在使用 listen 函数时,内核会根据传入的 backlog 参数与系统内参参数 somaxcoon,取其中最小值作为 backlog 的值,这也就是上面为上面 backlog 参数配置在 listen 指令的位置了


这个参数在内核中通常默认 128,可以通过 /proc/sys/net/core/somaxconn 查看,接着通过简单测试测试 backlog 值的选择


首先是初始配置,内核是默认 128,nginx 默认 511(这个在源码中可以查看),然后通过 ss 查看



下图是 nginx 源码中对 backlog 的定义



接着修改内核参数 somaxconn 为 1024,再通过 ss 查看



查看 nginx 对应的 Send-Q



从上面的结果来看确实是根据最小值来决定 backlog 的,所以你之前配置的内核参数,对于 nginx 来说,默认情况下,不管你设置多大,这个队列都是 511,并没有达到优化的效果


那么对于 nginx,对于 php-fpm,backlog 应该设置多大,是越大越好吗?下篇文章通过压测来看下 backlog 怎么设置合适

发布于: 2021 年 05 月 20 日阅读数: 51
用户头像

运维技术社区,坚持运维技术研究与分享 2020.07.14 加入

「运维研习社」技术社区发起人,同名公众号「运维研习社」、知识星球,专注运维技术研究分享,坚持原创,希望能和大家在运维路上结伴而行!

评论

发布
暂无评论
Nginx高并发调优中常被忽略的参数