SO_REUSEPORT socket选项介绍以及在nginx上的配置

news2024/11/27 20:30:57

SO_REUSEPORT (reuseport) 是网络的一个选项设置:

  1. 它能开启内核功能:网络链接分配 内核负载均衡,该功能允许多个进程/线程 bind/listen 相同的 IP/PORT,提升了新链接的分配性能。
  2. reuseport 也是内核解决 惊群问题 的优秀方案:每个进程可以 bind/listen 相同的 IP/PORT,相当于每个进程拥有独立的 listen socket 的完全队列,避免了共享 listen socket 的资源争抢,提升了并发的吞吐。内核通过哈希算法,将新链接相对均衡地分配到各个开启了 reuseport 属性的进程,所以资源的负载均衡得到解决。

nginx 开启 reuseport 功能后,性能有立竿见影的提升,我们结合 tcp 协议分析 nginx 的 reuseport 功能。

一、SO_REUSEPORT介绍和原理:

1、什么是SO_REUSEPORT:

Socket options
    The socket options listed below can be set by using setsockopt(2)
    and read with getsockopt(2) with the socket level set to
    SOL_SOCKET for all sockets.  Unless otherwise noted, optval is a
    pointer to an int.
...
    SO_REUSEPORT (since Linux 3.9)
                Permits multiple AF_INET or AF_INET6 sockets to be bound
                to an identical socket address.  This option must be set
                on each socket (including the first socket) prior to
                calling bind(2) on the socket.  To prevent port hijacking,
                all of the processes binding to the same address must have
                the same effective UID.  This option can be employed with
                both TCP and UDP sockets.

                For TCP sockets, this option allows accept(2) load
                distribution in a multi-threaded server to be improved by
                using a distinct listener socket for each thread.  This
                provides improved load distribution as compared to
                traditional techniques such using a single accept(2)ing
                thread that distributes connections, or having multiple
                threads that compete to accept(2) from the same socket.

                For UDP sockets, the use of this option can provide better
                distribution of incoming datagrams to multiple processes
                (or threads) as compared to the traditional technique of
                having multiple processes compete to receive datagrams on
                the same socket.

简单总结:

  • 允许多个线程/进程绑定到相同ip:port的套接字地址;这个选项必须设置在socket上调用 bind(2)方法之前;此外,为了防止端口劫持, 绑定到同一地址的所有进程必须具有 相同的有效 UID。
  • 对于 TCP 套接字,此选项允许 accept(2) 加载 通过以下方式改进多线程服务器中的分布 为每个线程使用不同的侦听器套接字。这个 提供改进的负载分配相比传统方式更好,例如:使用单个 accept(2)ing 分配连接的线程,或具有多个 竞争从同一个socket来accept(2)的线程。

2、SO_REUSEPORT解决了什么问题?

我们先看看 2013 年 3.9+ 版本内核提交的这个 Linux 内核功能 补丁 的注释。

soreuseport: TCP/IPv4 implementation
Allow multiple listener sockets to bind to the same port.

Motivation for soresuseport would be something like a web server
binding to port 80 running with multiple threads, where each thread
might have it's own listener socket.  This could be done as an
alternative to other models: 1) have one listener thread which
dispatches completed connections to workers. 2) accept on a single
listener socket from multiple threads.  In case #1 the listener thread
can easily become the bottleneck with high connection turn-over rate.
In case #2, the proportion of connections accepted per thread tends
to be uneven under high connection load (assuming simple event loop:
while (1) { accept(); process() }, wakeup does not promote fairness
among the sockets.  We have seen the  disproportion to be as high
as 3:1 ratio between thread accepting most connections and the one
accepting the fewest.  With so_reusport the distribution is
uniform.

Signed-off-by: Tom Herbert <therbert@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
 master
 v5.13 
…
 v3.9-rc1
@davem330
Tom Herbert authored and davem330 committed on 24 Jan 2013
1 parent 055dc21 commit da5e36308d9f7151845018369148201a5d28b46d

reuseport 选项主要解决了两个问题:

  1. (A 图)单个 listen socket 遇到的性能瓶颈。
  2. (B 图)单个 listen socket 多个线程同时 accept,但是多个线程资源分配不均。

其实它还解决了一个很重要的问题:

在 tcp 多线程场景中,(B 图)服务端如果所有新链接只保存在一个 listen socket 的 全链接队列 中,那么多个线程去这个队列里获取(accept)新的链接,势必会出现多个线程对一个公共资源的争抢,争抢过程中,大量资源的损耗。

而(C 图)有多个 listener 共同 bind/listen 相同的 IP/PORT,也就是说每个进程/线程有一个独立的 listener,相当于每个进程/线程独享一个 listener 的全链接队列,不需要多个进程/线程竞争某个公共资源,能充分利用多核,减少竞争的资源消耗,效率自然提高了。

3、原理:

TCP 客户端链接服务端,第一次握手,服务端被动收到第一次握手 SYN 包,内核就通过哈希算法,将客户端的链接分派到内核半链接队列,三次握手成功后,再将这个链接从半链接队列移动到某个 listener 的全链接队列中,提供 accept 获取。如下图:使用了OS_REUSEPORT选项后,服务端被动第一次握手,查找合适的 listener,详看源码(Linux 5.0.1)。

二、nginx上使用SO_REUSEPORT选项:

2013 年 Linux 内核添加了 reuseport 功能后,nginx 在 2015 年,1.9.1 版本也增加对应功能的支持,nginx 开启 reuseport 功能后,性能是原来的 2-3 倍,效果可谓立竿见影!(见官网:Socket Sharding in NGINX OSS Release 1.9.1)

1、开启reuseport:

# nginx.conf
# vim /usr/local/nginx/conf/nginx.conf
# 启动 4 个子进程。
worker_processes  4;
http {
    ...
    server {
        listen 80 reuseport;
        server_name localhost;
        ...
    }
    ...
}

 查看master和worker进程:

查看master和worker进程 LISTEN 80 端口情况。

因为配置文件设置了 worker_processes 4 需要启动 4 个子进程, nginx 进程发现配置文件关键字 listen 后添加了 reuseport 关键字,那么主进程先创建 4 个 socket 并设置 SO_REUSEPORT 选项,然后进行 bind 和 listen。

当 fork 子进程时,子进程拷贝了父进程的这 4 个 socket,所以你看到每个子进程都有相同 LISTEN 的 socket fd(7,8,9,10)。

如果没有配置reuseport,查看进程情况和端口情况如下:

2、网络图:

nginx 是多进程模型,Linux 环境下一般使用 epoll 事件驱动。

探索惊群 ⑥ - nginx - reuseport

3、性能对比:

3.1)nginx的锁模式和共享模式(reuseport):

为了让SO_REUSEPORT socket选项起作用(共享模式),应为HTTP或TCP(流模式)通信选项内的listen项直接引入新近的reuseport参数,就像下例这样:

http {
    server {
      listen 80 reuseport;
      server_name localhost;
    }

    stream {
      server {
        listen 88 reuseport;
      }
    }
}

引用reuseport参数后,对引用的socket,accept_mutex参数将会无效,因为互斥量(mutex)对reuseport来说是多余的。对没有使用reuseport的端口,设置accept_mutex仍然是有价值的。accept_mutex默认是开启的,下面提供两个Nginx Core模块互斥锁的指令。

1)accept_mutex

Syntax: accept_mutex on | off; 
Default:accept_mutex on; 
Context:events

互斥锁,就是各个worker接受用户请求的负载均衡锁,默认启用,表示让各个worker轮流地,序列化地响应用户请求;如果关闭那么所有的worker进程都会接收一个新的请求,如果连接数量不高的情况下,这么做只是会浪费系统资源。

2)lock_file

Syntax: lock_file file; 
Default:lock_file logs/nginx.lock; 
Context:main

既然启动了负载均衡锁,那么就需要指定一个锁文件了。nginx使用锁机制来实现accept_mutex和序列化访问共享内存。

3.2)实验对比:

在一个36核的AWS实例运行wrk基准测试工具,测试4个NGINX工作进程。为了减少网络的影响,客户端和NGINX都运行在本地,并且让NGINX返回OK字符串而不是一个文件。我比较三种NGINX配置:默认(等同于accept_mutex on ),accept_mutex off和reuseport。如图所示,reuseport的每秒请求是其余的两到三倍,同时延迟和延迟标准差也是减少的。

我又运行了另一个相关的性能测试——客户端和NGINX分别在不同的机器上且NGINX返回一个HTML文件。如下表所示,用reuseport减少的延迟和之前的性能测试相似,延迟的标准差减少的更为显著(接近十分之一)。其他结果(没有显示在表格中)同样令人振奋。使用reuseport ,负载被均匀分离到了worker进程。在默认条件下(等同于 accept_mutex on),一些worker分到了较高百分比的负载,而用accept_mutex off所有worker都受到了较高的负载。

在这些性能测试中,连接请求的速度是很高的,但是请求不需要大量的处理。其他的基本的测试应该指出——当应用流量符合这种场景时 reuseport 也能大幅提高性能。(reuseport 参数在 mail 上下文环境下不能用在 listen 指令下,例如email,因为email流量一定不会匹配这种场景。)我们鼓励你先测试而不是直接大规模应用。关于测试NGNIX性能的一些技巧,看看Konstantin Pavlov在nginx2014大会上的演讲。

Nginx listen reuseport参数带来的性能提升 – 运维那点事

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

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

相关文章

CoSENT:比sentence bert更好的向量表征

本文是对https://spaces.ac.cn/archives/8847文章的总结 有监督的文本表征主流方案是sentence bert&#xff0c;虽然sentence BERT效果还行&#xff0c;但是存在训练和预测不一致的问题&#xff0c;而一些文章也指出而如果直接优化预测目标cos值&#xff0c;效果往往特别差&…

方寸间联结世界,中国直播电商如何诠释“人类命运共同体”?

十几个人凝神屏息地盯着屏幕&#xff0c;仿佛静止了一般&#xff0c;眼睛一眨不眨&#xff0c;生怕错过了什么。直到听到屏幕另一端终于有了动静&#xff0c;悬在他们心里的石头才落下——“谢谢大家的支持&#xff0c;全部没有了。” 话音未落&#xff0c;这边已爆发了欢呼声…

只工作,不上班,「远程办公」是不是理想的工作方式?

在我们90后眼中&#xff0c;上班和工作是两回事。准确来说。上班是为别人做事&#xff0c;而工作是为自己。 圆桌派有一期的话题是“不想工作怎么破&#xff1f;”当时&#xff0c;几位嘉宾说&#xff1a;“不是不想工作&#xff0c;是不想上班”&#xff0c;“周围很多年轻人…

【linux】之 kubernetes安装

一、容器编排工具 docker machinedocker composedocker swarm docker servicedocker stack kubernetesmesosmarathon 二、PaaS平台 OpenShiftRancher 三、认识kubernetes 官方网址 https://kubernetes.io/ https://kubernetes.io/zh/ 中文社区 http://docs.kubernetes.org…

libco 宏分析

// 下面是从libco中导出的宏 #include <iostream> using namespace std;/*以下是计算参数的个数&#xff0c;最多支持7个参数 */ #define comac_get_args_cnt( ... ) comac_arg_n( __VA_ARGS__ ) #define comac_arg_n( _0,_1,_2,_3,_4,_5,_6,_7,N,...) N #define comac_a…

完整的PCB生产工艺到底是怎样的?华秋告诉你

前面&#xff0c;与朋友们分享了一些关于PCB生产工艺的事情。 有的朋友看了后非常感兴趣&#xff0c;私信说——现在的各种PCB资料满天飞&#xff0c;经常彼此间相互不一致&#xff0c;甚至对立&#xff0c;能给我们再讲讲&#xff0c;完整的PCB生产工艺到底是怎样的吗&#x…

Java 8函数式编程

函数式接口 一个接口中&#xff0c;有且只有一个抽象方法&#xff0c;这个接口就叫做函数式接口。常常使用FunctionalInterface注解作为编译校验。满足函数式接口的要求&#xff0c;才能校验通过&#xff0c;否则会在校验阶段失败。 接口中有且只能有一个抽象方法&#xff0c;…

STM32F4 | 外部中断实验

文章目录一、STM32F4 外部中断简介二、硬件设计三、软件设计四、实验现象五、STM32CubeMX 配置外部中断本章我们将介绍如何将 STM32F429 的 IO 口作为外部中断输入。一、STM32F4 外部中断简介 这里首先介绍STM32F4 IO 口中断的一些基础概念。STM32F4 的每个 IO 都可以作为外部…

实验五图形用户界面编程

目录 一、目的与任务 二、内容、要求与安排方式 三、实验设备 四、实验步骤 一、目的与任务 掌握常用事件及其处理模型&#xff1b;掌握常用GUI控制组件的使用及其事件的处理&#xff1b;掌握菜单的使用以及对话框的使用。 二、内容、要求与安排方式 1、实验内容与要求&…

SpringCloud系列(五)Nacos 注册中心配置管理的设置及使用

介绍几种 Nacos 常用的配置, 如统一配置管理的步骤, 如何配置自动刷新及多环境配置优先级问题. Nacos 配置管理⚽️ 统一配置管理⚽️⚽️配置自动刷新⚽️⚽️⚽️ 多环境配置优先级⚽️ 统一配置管理 步骤一: 在 Nacos 中添加配置信息, 如添加时间格式的配置内容; 步骤二: …

Ribbon实战与原理剖析

一、ribbon概述 1、ribbon简介 目前主流的负载方案分为以下两种&#xff1a; 集中式负载均衡&#xff0c;在消费者和服务提供方中间使用独立的代理方式进行负载&#xff0c;有硬件的&#xff08;比如 F5&#xff09;&#xff0c;也有软件的&#xff08;比如 Nginx&#xff0…

读写锁的学习与实验

目录 目录 1&#xff0c;场景 2&#xff0c;接口 3&#xff0c;场景模拟 1&#xff0c;场景 有一种场景&#xff0c;读者多&#xff0c;写者少&#xff0c;绝大多数的情况下我们都是在进行读取而不修改&#xff0c;只有少数的情况下我们才会修改。 场景一&#xff1a;比如…

解决jenkins构建失败,空间不足问题

随着构建次数过多&#xff0c;之后jenkins构建会出现空间不足的问题&#xff0c;解决方式如下&#xff1a; 目录 1.配置时&#xff0c;去除旧的构建任务 2.使用脚本&#xff0c;删除历史构建 3.清理磁盘空间 4.重新加载服务器节点 1.配置时&#xff0c;去除旧的构建任务 2…

计算机网络(自顶向下)学习笔记——路由选择算法

第五章—路由选择算法 5.1、路由的概念 路由:按照某种指标(传输延迟,所经过的站点数目等)找到一条 从源节点到目标节点的较好路径 较好路径: 按照某种指标较小的路径指标:站数, 延迟,费用,队列长度等, 或者是一些单纯指标的加权平均采用什么样的指标,表示网络使用者希望网络…

m基于优化算法的多车辆的路径规划matlab仿真,对比GA,PSO以及烟花算法

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 路径规划是运动规划的主要研究内容之一。运动规划由路径规划和轨迹规划组成&#xff0c;连接起点位置和终点位置的序列点或曲线称之为路径&#xff0c;构成路径的策略称之为路径规划。路径规划在…

微软12月多个安全漏洞修复解决方案

安全狗应急响应中心监测到&#xff0c;微软发布了2022年12月份安全更新&#xff0c;事件等级&#xff1a;严重&#xff0c;事件评分&#xff1a;10.0。此次安全更新发布了52个漏洞的补丁&#xff0c;主要覆盖了以下组件&#xff1a;Azure; Office and Office Components; SysIn…

提高电网的稳态稳定性(Matlab代码实现)

目录 1 概述 2 稳态稳定性分析 2.1 系统模型 2.2 稳态稳定性 2.3 问题说明 3 仿真结果 4 一点小智慧 5 Matlab代码实现 1 概述 随着电力系统的复杂性和规模的增加&#xff0c;电力系统的有效控制变得越来越困难。我们提出了一种自动控制策略&#xff0c;该策略基于通过…

如何使用typeScript实现贪吃蛇游戏?

1.配置文件 配置文件写过一次之后&#xff0c;可以复制粘贴使用&#xff0c;修改部分细节就可以了。 package.json {"name": "snake","version": "1.0.0","description": "","main": "index.js&q…

网络协议——RPC协议综述

拿最简单的场景&#xff0c;客户端调用一个加法函数&#xff0c;将两个整数加起来&#xff0c;返回它们的和。 如果放在本地调用&#xff0c;那是简单的不能再简单了&#xff0c;。但是一旦变成了远程调用&#xff0c;门槛一下子就上去了。 如何解决这五个问题&#xff1f; …

秦力洪复盘2022:蔚来的长板和误判

作者 | 张祥威 编辑 | 王博最初我们看蔚来&#xff0c;觉得它是中国的特斯拉。后来它主动挑战宝马&#xff0c;以46万的平均单价在高端品牌阵营厮杀&#xff0c;看上去又具备成为宝马的潜力。再到后来&#xff0c;蔚来宣布将推出全新品牌&#xff0c;喊话月销5万辆&#xff0c;…