[转帖]探索惊群 ⑥ - nginx - reuseport
https://wenfh2020.com/2021/10/12/thundering-herd-tcp-reuseport/
SO_REUSEPORT (reuseport) 是网络的一个选项设置,它能开启内核功能:网络链接分配 内核负载均衡。
该功能允许多个进程/线程 bind/listen 相同的 IP/PORT,提升了新链接的分配性能。
nginx 开启 reuseport 功能后,性能有立竿见影的提升,我们结合 tcp 协议分析 nginx 的 reuseport 功能。
reuseport 也是内核解决 惊群问题 的优秀方案。
每个进程可以 bind/listen 相同的 IP/PORT,相当于每个进程拥有独立的 listen socket 的完全队列,避免了共享 listen socket 的资源争抢,提升了并发的吞吐。
内核通过哈希算法,将新链接相对均衡地分配到各个开启了 reuseport 属性的进程,所以资源的负载均衡得到解决。
- 探索惊群 ①
- 探索惊群 ② - accept
- 探索惊群 ③ - nginx 惊群现象
- 探索惊群 ④ - nginx - accept_mutex
- 探索惊群 ⑤ - nginx - NGX_EXCLUSIVE_EVENT
- 探索惊群 ⑥ - nginx - reuseport(★)
- 探索惊群 ⑦ - 文件描述符透传
1. 概述
1.1. what
从下面这段英文提取一些关键信息:
SO_REUSEPORT 是网络的一个选项设置,它允许多个进程/线程 bind/listen 相同的 IP/PORT,在 TCP 的应用中,它是一个新链接分发的(内核)负载均衡功能,它提升了新链接的分配性能(针对 accept )。
1 |
Socket options |
注释文字来源 (链接需要FQ):socket(7) — Linux manual page
1.2. why
SO_REUSEPORT 功能解决了什么问题?我们先看看 2013 年 3.9+ 版本内核提交的这个 Linux 内核功能 补丁 的注释。
1 |
soreuseport: TCP/IPv4 implementation |
reuseport 选项主要解决了两个问题:
- (A 图)单个 listen socket 遇到的性能瓶颈。
- (B 图)单个 listen socket 多个线程同时 accept,但是多个线程资源分配不均。

其实它还解决了一个很重要的问题:
在 tcp 多线程场景中,(B 图)服务端如果所有新链接只保存在一个 listen socket 的 全链接队列 中,那么多个线程去这个队列里获取(accept)新的链接,势必会出现多个线程对一个公共资源的争抢,争抢过程中,大量资源的损耗。
而(C 图)有多个 listener 共同 bind/listen 相同的 IP/PORT,也就是说每个进程/线程有一个独立的 listener,相当于每个进程/线程独享一个 listener 的全链接队列,不需要多个进程/线程竞争某个公共资源,能充分利用多核,减少竞争的资源消耗,效率自然提高了。
1.3. how
SO_REUSEPORT 功能使用,可以通过网络选项进行设置,在 bind 前面设置即可,使用比较简单。
1 |
int fd, reuse = 1; |
2. 原理
TCP 客户端链接服务端,第一次握手,服务端被动收到第一次握手 SYN 包,内核就通过哈希算法,将客户端的链接分派到内核半链接队列,三次握手成功后,再将这个链接从半链接队列移动到某个 listener 的全链接队列中,提供 accept 获取。
- 三次握手流程。

图片来源:TCP 三次握手(内核)
- 服务端被动第一次握手,查找合适的 listener,详看源码(Linux 5.0.1)。

1 |
/* include/net/inet_hashtables.h */ |
3. nginx
2013 年 Linux 内核添加了 reuseport 功能后,nginx 在 2015 年,1.9.1 版本也增加对应功能的支持,nginx 开启 reuseport 功能后,性能是原来的 2-3 倍,效果可谓立竿见影!
详细请参考 nginx 官方文档:Socket Sharding in NGINX Release 1.9.1
接下来我们看看 nginx 是如何支持 reuseport 的。
3.1. 开启 SO_REUSEPORT
修改 nginx 配置,在 nginx.conf 里,listen 关键字后面添加 ‘reuseport’。
1 |
# nginx.conf |
3.2. 工作流程
启动测试 nginx,1 master / 4 workers,监听 80 端口。
3.2.1. 进程
- 父子进程。
1 |
# ps -ef | grep nginx |
父子进程 LISTEN 80 端口情况。
因为配置文件设置了
worker_processes 4需要启动 4 个子进程, nginx 进程发现配置文件关键字 listen 后添加了 reuseport 关键字,那么主进程先创建 4 个 socket 并设置 SO_REUSEPORT 选项,然后进行 bind 和 listen。当 fork 子进程时,子进程拷贝了父进程的这 4 个 socket,所以你看到每个子进程都有相同 LISTEN 的 socket fd(6,7,8,9)。
1 |
# lsof -i:80 | grep nginx |
3.2.2. 网络初始流程
nginx 是多进程模型,Linux 环境下一般使用 epoll 事件驱动。

- strace 监控 nginx 进程的系统调用流程。
1 |
# strace -f -s 512 -o /tmp/nginx.log /usr/local/nginx/sbin/nginx |
- 分析总结一下 strace 采集的系统调用日志。
1 |
# 如果有 N 个子进程就创建 N 个 socket 并对其设置,绑定地址和监听端口。 |
- 源码函数调用层次。
1 |
# 函数调用层次关系。 |
4. 参考
- 《Linux 内核源代码情景分析》
- 多个进程绑定相同端口的实现分析[Google Patch]
- 【优化】nginx启用reuseport
- Linux TCP SO_REUSEPORT — Usage and implementation
- 再谈Linux epoll惊群问题的原因和解决方案
- [epoll 源码走读] epoll 实现原理
- socket(7) — Linux manual page
- Socket Sharding in NGINX Release 1.9.1
- Linux 网络层收发包流程及 Netfilter 框架浅析
- Why does one NGINX worker take all the load?
- 深入浅出 Linux 惊群:现象、原因和解决方案
- Linux 4.6内核对TCP REUSEPORT的优化
- [内核源码] 网络协议栈 listen (tcp)
- 本文作者: wenfh2020
- 本文链接: https://wenfh2020.com/2021/10/12/thundering-herd-tcp-reuseport/
- 版权声明: 本文可以自由拷贝,转载,请注明出处,谢谢!
[转帖]探索惊群 ⑥ - nginx - reuseport的更多相关文章
- NGINX怎样处理惊群的
写在前面 写NGINX系列的随笔,一来总结学到的东西,二来记录下疑惑的地方,在接下来的学习过程中去解决疑惑. 也希望同样对NGINX感兴趣的朋友能够解答我的疑惑,或者共同探讨研究. 整个NGINX系列 ...
- “惊群”,看看nginx是怎么解决它的
在说nginx前,先来看看什么是“惊群”?简单说来,多线程/多进程(linux下线程进程也没多大区别)等待同一个socket事件,当这个事件发生时,这些线程/进程被同时唤醒,就是惊群.可以想见,效率很 ...
- Nginx学习之一-惊群现象
惊群问题(thundering herd)的产生 在建立连接的时候,Nginx处于充分发挥多核CPU架构性能的考虑,使用了多个worker子进程监听相同端口的设计,这样多个子进程在accept建立新连 ...
- Nginx惊群处理
惊群:是指在多线程/多进程中,当有一个客户端发生链接请求时,多线程/多进程都被唤醒,然后只仅仅有一个进程/线程处理成功,其他进程/线程还是回到睡眠状态,这种现象就是惊群. 惊群是经常发生现在serve ...
- 【转载】“惊群”,看看nginx是怎么解决它的
原文:http://blog.csdn.net/russell_tao/article/details/7204260 在说nginx前,先来看看什么是“惊群”?简单说来,多线程/多进程(linux下 ...
- Nginx中的惊群现象解决方法
*什么是惊群现象?Nginx中用了什么方法来避免这种问题的发生?本篇就解决这两个问题...→_→* 惊群现象的定义与危害 在Nginx中,每一个worker进程都是由master进程fork出来的.m ...
- 【Nginx】惊群问题
转自:江南烟雨 惊群问题的产生 在建立连接的时候,Nginx处于充分发挥多核CPU架构性能的考虑,使用了多个worker子进程监听相同端口的设计,这样多个子进程在accept建立新连接时会有争抢,这会 ...
- Nginx模型 & 惊群问题
这篇写的不错 http://www.cnblogs.com/linguoguo/p/5511293.html Nginx为啥性能高-多进程异步IO模型 1. 对于每个worker进程来说,独立的进程, ...
- Nginx惊群问题
Nginx惊群问题 "惊群"概念 所谓惊群,可以用一个简单的比喻来说明: 一群等待食物的鸽子,当饲养员扔下一粒谷物时,所有鸽子都会去争抢,但只有少数的鸽子能够抢到食物, 大部分鸽子 ...
- nginx&http 第三章 惊群
惊群:概念就不解释了. 直接说正题:惊群问题一般出现在那些web服务器上,Linux系统有个经典的accept惊群问题,这个问题现在已经在内核曾经得以解决,具体来讲就是当有新的连接进入到accept队 ...
随机推荐
- Docker、pre-commit 导致的 git commit 报错:找不到 python 3.8
到这个问题的原因可能有很多,这里只是记录下针对我遇到这这跟题的原因及解决方法 问题描述 执行 git commit 命令,报错 /usr/bin/env: 'python3.8': No such f ...
- 文心一言 VS 讯飞星火 VS chatgpt (44)-- 算法导论6.1 1题
一.在高度为h的堆中,元素个数最多和最少分别是多少? 文心一言: 在高度为 h 的二叉搜索树(BST)中,元素个数最多和最少的情况分别如下: 1.最多情况:当每个节点都包含两个子节点时,BST 中的元 ...
- Cesium渲染一帧中用到的图形技术
译者注:本文翻译自Cesium官方博文<Graphics Tech in Cesium - Rendering a Frame>,May 14, 2015 by Patrick Cozzi ...
- 十分钟从入门到精通(上)——OBS权限配置
[摘要]作为公有云的数据底座,大量的应用场景产生的数据都会存储到OBS对象存储服务中,如直播.电商.大数据可视化.机器学习.物联网等.作为公有云的海量存储基础服务, OBS提供了灵活的权限配置功能,解 ...
- JDK1.6中String类的坑,快让我裂开了…
摘要:JVM优化的目标就是:尽可能让对象都在新生代里分配和回收,尽量别让太多对象频繁进入老年代,避免频繁对老年代进行垃圾回收,同时给系统充足的内存大小,避免新生代频繁的进行垃圾回收. 本文分享自华为云 ...
- 实践丨手把手教你用STM32设计WiFi语音播报日程表
摘要:随着电子产品的发展,数字日程表这项应用在人们工作和生活中起到越来越重要的作用.本文带领大家基于STM32自己动手制作一个WiFi语音播报日程表. 本文分享自华为云社区<基于STM32设计的 ...
- 云小课 | 网络知识一箩筐——NAT网关,让IP地址华丽变身,轻松实现内外网互通
阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课) 或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要: 网络知识一箩筐 ...
- MongoDB 读写分离——MongoDB 安装
下载安装包:https://www.mongodb.com/try/download/community 同一台电脑装了两服务,所以下载zip包,单机服务 mis 安装方便些 解压并重命名. 4.2 ...
- byte[] 数组,创建的时候赋初始值
C# //创建一个长度为10的byte数组,并且其中每个byte的值为0x08. byte[] myByteArray = Enumerable.Repeat((byte)0x08, 10).ToAr ...
- CodeForces - 469A I Wanna Be the Guy
There is a game called "I Wanna Be the Guy", consisting of n levels. Little X and his frie ...