写点什么

高并发调优 backlog 多大合适?

发布于: 2021 年 05 月 21 日

接上一篇,关于 Nginx 高并发优化中对于 backlog 参数的配置


那么对于 nginx,对于 php-fpm,backlog 应该设置多大,是越大越好吗?backlog 怎么设置合适?这是上篇文章中遗留的几个问题


接着上篇文章Nginx高并发调优中常被忽略的参数中,最后部分,通过查看 nginx 源码发现 nginx 源码中定义 backlog 为 511,其实在 php-fpm 配置文件中,同样默认 backlog 是 511



包括 redis,在默认配置文件中也有 backlog 配置,默认也是 511



其实在 redis 注释中已经解释很清楚了,当你需要处理高并发得场景时,需要较大得 backlog 来处理堆积得请求,上篇文章对原理已经做了较全面的解释,网上也有很多大牛关于 tcp 全连接、半连接的文章讲解,今天主要想测试下,backlog 在优化设置时,应该怎么设置


为了尽量排除带宽影响,我这里直接用两台内网的机子,一台作为客户端用 ab 去请求,另外一台作为服务端,服务端是一台 centos7,没有优化过的系统



首先说一下 ss 的 Recv-Q 和 Send-Q



在 ss 命令的结果中,如果该条记录为监听端口,则 Recv-Q 表示 accept 队列中元素的个数,Send-Q 表示 accept 队列中队列的容量,所以从监听端口这行正好可以看到队列的情况


接着开始测试,第一步,先就默认 backlog 为 128 的情况下,用 ab 进行测试



直接开了两个窗口,用 watch 执行 ss 命令,0.1s 刷新,在客户端用 ab 200 并发请求,开始瞬间 php 的 Recv-Q 就满了(因为我这里 nginx 连接 php 用的是 socket 的方式,所以监听的是 socket,不是端口),接着查看 ab 结果



69 次失败请求



查看 nginx 错误日志,69 条错误日志,都是 sock 文件资源不可用,如果是用端口的形式,应该是请求超时或连接被重置,这个具体根据 php 执行时间已经 nginx 配置超时时间决定


接着调大内核 somaxconn,让 somaxconn 大于 nginx 和 php 的默认 backlog,也就是 511,这里设置为 1024,在接着测试



查看 php-cgi 的 Send-Q,注意这里 nginx 或者 php-fpm 都要 restart 才能生效



接着查看 nginx 的 Send-Q



接着 ab 进行测试,同时实时查看 Recv-Q 情况,我先仍然用刚才的 ab 参数进行测试



截图有点慢了,打的时候 Recv-Q 已经到 198 了,接着快速下降,看下 ab 测试结果



已经没有失败请求了,接着调大 ab 参数,再进行同样的测试



手慢了,ab 打的瞬间 Recv-Q 是 512,队列打满了,接着查看结果,不出意外肯定会有失败请求



从目前测试的结果来看,最直观的就是,backlog 增大,对于能处理的并发请求来说也在增大,所以 backlog 优化是必须的,接着继续增加 backlog 进行测试



还是用 600 并发



没有问题,都能够正常处理,继续增加并发到 1025



查看结果



接着想看下 backlog 太大会不会有什么影响,进行如下配置



接着 ab 测试(测试服务器不一定能扛住,这里 ab 最大并发 2w)




从结果来看,没有问题,backlog 越大越好


但其实这里有个问题,就是我这里测试的只是单 php 脚本,并没有涉及到业务代码,也不查询数据库,所以 php 能够快速处理,服务器不会崩,那么为什么 nginx、php-fpm、redis,都默认设置 511,而不设置很大的值,其实在 php 历史上,backlog 是修改过的(从其他文章看到的),也是从 511,修改到 65535,提交者也是认为 backlog 数量越大越好,即便出现 timeout 也比 syn 队列满了后,内核忽略掉 TCP SYN 请求要好



但是在后面又将 backlog 改回 511



其中理由是“backlog 值为 65535 太大了。会导致前面的 nginx(或者其他客户端)超时”,而且提交者举例计算了一下,假设 FPM 的 QPS 为 5000,那么 65535 个请求全部处理完需要 13s 的样子。但前端的 nginx(或其他客户端)已经等待超时,关闭了这个连接。当 FPM 处理完之后,再往这个 SOCKET ID 写数据时,却发现连接已关闭,得到的是“error: Broken Pipe”,在 nginx、redis、apache 里,默认的 backlog 值都是 511。故这里也建议改为 511


所以我的建议是,用压测的方法,持续调整测试,取一个适合你业务的最大 backlog 值,一定要以业务代码进行测试,而不是单纯的调大 backlog。

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

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

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

评论

发布
暂无评论
高并发调优backlog多大合适?