Linux 3.9内核新特性SO_REUSEPORT

教你使用 SO_REUSEPORT 套接字选项提升服务性能 Linux 网络栈中有一个相对较新的特性——SO_REUSEPORT 套接字选项,可以使用它来提升你的服务性能。图 1: 上面的服务是使用并行监听器来避免请求连接瓶颈,而下面的服务只使用一个监听器来接收连接概要HAProxy 和 NGINX 是少数几个使用 Linux 网络栈中 TCP 的 SO_REUSEPORT 套接字选项[1]的应用程序。这个选项最初是在 4.4 BSD 中引入的,帮助在现在大型多核系统中实现高性能服务。 阅读详情

转自:http://www.cnblogs.com/Anker/p/7076537.html

1、前言

  昨天总结了一下Linux下网络编程“惊群”现象,给出Nginx处理惊群的方法,使用互斥锁。为例发挥多核的优势,目前常见的网络编程模型就是多进程或多线程,根据accpet的位置,分为如下场景:

  (1)单进程或线程创建socket,并进行listen和accept,接收到连接后创建进程和线程处理连接

  (2)单进程或线程创建socket,并进行listen,预先创建好多个工作进程或线程accept()在同一个服务器套接字、

                      

这两种模型解充分发挥了多核CPU的优势,虽然可以做到线程和CPU核绑定,但都会存在:

  • 单一listener工作进程胡线程在高速的连接接入处理时会成为瓶颈
  • 多个线程之间竞争获取服务套接字
  • 缓存行跳跃
  • 很难做到CPU之间的负载均衡
  • 随着核数的扩展,性能并没有随着提升

参考:http://www.blogjava.net/yongboy/archive/2015/02/12/422893.html

Linux kernel 3.9带来了SO_REUSEPORT特性,可以解决以上大部分问题。

2、SO_REUSEPORT解决了什么问题

SO_REUSEPORT支持多个进程或者线程绑定到同一端口,提高服务器程序的性能,解决的问题:

  • 允许多个套接字 bind()/listen() 同一个TCP/UDP端口
    • 每一个线程拥有自己的服务器套接字
    • 在服务器套接字上没有了锁的竞争
  • 内核层面实现负载均衡
  • 安全层面,监听同一个端口的套接字只能位于同一个用户下面

其核心的实现主要有三点:

  • 扩展 socket option,增加 SO_REUSEPORT 选项,用来设置 reuseport。
  • 修改 bind 系统调用实现,以便支持可以绑定到相同的 IP 和端口
  • 修改处理新建连接的实现,查找 listener 的时候,能够支持在监听相同 IP 和端口的多个 sock 之间均衡选择。

有了SO_RESUEPORT后,每个进程可以自己创建socket、bind、listen、accept相同的地址和端口,各自是独立平等的。让多进程监听同一个端口,各个进程中accept socket fd不一样,有新连接建立时,内核只会唤醒一个进程来accept,并且保证唤醒的均衡性。

include <stdio.h>
#include <unistd.h>
#include <sys/types.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <assert.h>  
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>

#define IP   "127.0.0.1"
#define PORT  8888
#define WORKER 4
#define MAXLINE   4096

int worker(int i)
{
    struct sockaddr_in address;  
    bzero(&address, sizeof(address));  
    address.sin_family = AF_INET;  
    inet_pton( AF_INET, IP, &address.sin_addr);  
    address.sin_port = htons(PORT);  

    int listenfd = socket(PF_INET, SOCK_STREAM, 0);  
    assert(listenfd >= 0);  

    int val =1;
    /*set SO_REUSEPORT*/
    if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val))<0) {
        perror("setsockopt()");         
    }    
    int ret = bind(listenfd, (struct sockaddr*)&address, sizeof(address));  
    assert(ret != -1);  

    ret = listen(listenfd, 5);  
    assert(ret != -1);  
    while (1) {
        printf("I am worker %d, begin to accept connection.\n", i);
        struct sockaddr_in client_addr;  
        socklen_t client_addrlen = sizeof( client_addr );  
        int connfd = accept( listenfd, ( struct sockaddr* )&client_addr, &client_addrlen );  
        if (connfd != -1) {
            printf("worker %d accept a connection success. ip:%s, prot:%d\n", i, inet_ntoa(client_addr.sin_addr), client_addr.sin_port);
        } else {
            printf("worker %d accept a connection failed,error:%s", i, strerror(errno));
        }
        char buffer[MAXLINE];
        int nbytes = read(connfd, buffer, MAXLINE);
        printf("read from client is:%s\n", buffer);
        write(connfd, buffer, nbytes);
        close(connfd);
    }
    return 0;
}

int main()
{
    int i = 0;
    for (i = 0; i < WORKER; i++) {
        printf("Create worker %d\n", i);
        pid_t pid = fork();
        /*child  process */
        if (pid == 0) {
            worker(i);
        }
        if (pid < 0) {
            printf("fork error");
        }
    }
    /*wait child process*/
    while (wait(NULL) != 0)
        ;
    if (errno == ECHILD) {
        fprintf(stderr, "wait error:%s\n", strerror(errno));
    }
    return 0;
}

我的测试机器内核版本为:

测试结果如下所示:

从结果可以看出,四个进程监听相同的IP和port。

 4、参考资料

http://lists.dragonflybsd.org/pipermail/users/2013-July/053632.html

http://www.blogjava.net/yongboy/archive/2015/02/12/422893.html 

http://m.blog.chinaunix.net/uid-10167808-id-3807060.html

重学TCP协议(12)SO_REUSEADDR、SO_REUSEPORT、SO_LINGER 1. SO_REUSEADDR 假如服务端出现故障,主动断开连接以后,需要等 2 个 MSL 以后才最终释放这个连接,而服务重启以后要绑定同一个端口,默认情况下,操作系统的实现都会阻止新的监听套接字绑定到这个端口上。启用 SO_REUSEADDR 套接字选项可以解除这个限制。 2. SO_REUSEPORT 默认情况下,一个 IP、端口组合只能被一个套接字绑定,Linux 内核从 3.9 版本开始引入一个新的 socket 选项 SO_REUSEPORT,又称为 port sharding,允许多个套接字监 阅读详情

相关推荐

说说PSTN、ISDN、 ADSL三种互联网接入方式的区别。

互联网的接入方式: 电话拨号接入(PSTN) ISDN接入 ADSL接入 Cable MODEM接入 局域网接入 光纤接入(FDDI) 卫星接入 DDN专线 目前来说,ADSL和Cable MODEM比较常用,今天我们就先来说说PSTN、ISDN和ADSL的区别。 电话拨号接入(PSTN/POTS,Public Switched Telephone Network / Public Oold Telephone Service) 数据终端设备(DTE)通过数据通信设备(DCE)再连

Winyaz的博客 2万+

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

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

赶路人儿 3894

从0到1:.NET 9 OpenAPI全攻略!Swagger vs Scalar UI谁更强?

OpenAPI:.NET 9的智能文档革命 本文深入解析.NET 9的OpenAPI支持,对比Swagger UI与Scalar UI的优劣,提供实战代码示例: 一键生成:AddOpenApi()+MapOpenApi()快速生成标准文档 UI工具对决: Swagger UI功能全面但复杂 Scalar UI简约现代,原生支持cURL/HTTPie 进阶技巧: XML注释增强文档可读性 自定义Transformer实现文档动态修改 🔥核心价值:.NET 9的OpenAPI方案显著降低API文档维护成本,开

java专栏 1427

Linux 最新SO_REUSEPORT特性

1、前言   昨天总结了一下Linux下网络编程“惊群”现象,给出Nginx处理惊群的方法,使用互斥锁。为例发挥多核的优势,目前常见的网络编程模型就是多进程或多线程,根据accpet的位置,分为如下场景:   (1)单进程或线程创建socket,并进行listen和accept,接收到连接后创建进程和线程处理连接   (2)单进程或线程创建socket,并进行listen,预先创建好多...

weixin_33778544的博客 622

从零编写linux0.11 - 第二章 内核初始化

编程环境:Ubuntu Kylin 16.04 代码仓库:https://gitee.com/AprilSloan/linux0.11-project linux0.11源码下载(不能直接编译,需进行修改) 1.添加内核 进入内核后也不是马上进入main函数,上一章只是暂时设置gdt,此外还要设置idt和其他的一些初始化操作,这些内容也要使用汇编进行编写,此处采用AT&T格式的汇编。 以下为head.s的内容,为了简单起见,内容还是一个死循环。 .globl startup_32 startup_3

皓空Fly的博客 1264

【宠物识别系统】设计框架

能跑通的 Demo。收集 10,000 张同品种但不同个体的图片。训练ArcFace模型,验证准确率能否达到 99% 以上。搭建Milvus向量数据库。开发移动端 App/小程序。加入“图像质量检测”和“用户反馈纠错”功能。你是更偏向于做软件服务(如寻宠App、保险API),还是做软硬结合的产品(如智能喂食器)?这决定了我们下一步是深挖云端高并发架构,还是边缘端模型压缩。更偏向于软件,应用更广泛些,继续既然专注于纯软件/SaaS (Software as a Service) 方向。

百态·数智思维 | 聚焦大数据、量化与未来AI 1413

SO_REUSEPORT使用示例

SO_REUSEPORT使用示例最近计划对之前写过的后台多线程服务器重构,其中涉及到并发模型,之前是一个listener线程+N个worker线程,即用一个线程监控tcp端口,来了请求,accept一个新的socket后,丢给后面的worker线程池去处理。现在想用Linux内核支持的SO_REUSEPORT特性,减少listener线程跟worker线程之间的锁,同时去掉listener线程。示例

c359719435的专栏 1万+

CATIA_DELMIA_V5R2019安装包下载及安装教程破解

CATIA_V5R2019/DELMIA_V5R2019安装包下载及安装教程破解

一只机械工装熊的博客 8334

网络编程中的SO_REUSEADDR和SO_REUSEPORT参数详解

在BSD中,SO_REUSEADDR选项有两个用户:setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,(const void *)&reuse , sizeof(int));目的:当服务端出现timewait状态的链接时,确保server能够重启成功。注意:SO_REUSEADDR只有针对time-wait链接(linux系统time-wait连接持续时间为1min),确保server重启成功的这一个作用。举个time_wait的连接通过so_reuseaddr选项

赶路人儿 6308

软件工程案例教程·韩万江【课后习题】

!!!!

weixin_57858263的博客 6419

win10自动修复-无限循环【通用完美】超简单解决办法

2020.02.14今个我的笔记本电脑(Thinkpad Carbon 7 X1)(win10)早晨起来发现蓝屏,上面显示自动修复失败,重启后依然自动修复失败,不断手动重启,始终是修复失败。然后上网开始搜集资料找解决办法。 前边介绍关闭自动修复,如何找出错文件的方法;如果想看最终解决办法,直接看第三部分 上网就会发现这种现象很常见,同时是电脑自动安装系统更新,或者安装某些驱动出现。解决办法也大...

y15941300574的博客 19万+

Linux 端口复用:SO_REUSEPORT

Linux 端口复用:SO_REUSEPORT简介

小立仔 3673

《八》:玩家位置同步(玩家防碰撞)

在VR大空间体验中,由于玩家佩戴头显设备无法直接观察彼此位置,容易发生碰撞。因此,需要将玩家的实时位置信息绘制在虚拟空间中,实现位置可视化。通过获取头显的位置和旋转角度等数据,可以推算出玩家的移动状态和位置。使用可序列化的玩家结构体,通过UDP将玩家数据发送到服务器,服务器接收并反序列化数据后,同步所有玩家的最新信息至各客户端。客户端根据接收到的数据渲染虚拟人物模型,实现动态位置更新。这一过程涉及数据序列化、反序列化、网络通信和实时渲染等技术,确保玩家在虚拟空间中的位置同步和可视化。

unitygroup的博客 413

Linux内核中reuseport的演进

SO_REUSEPORT选项在Linux 3.9被引入内核,在这之前也有一个很像的选项SO_REUSEADDR。如果你不太清楚这两者的区别和联系,建议阅读How do SO_REUSEADDR and SO_REUSEPORT differ?。 如果不想读,那么下面这一节算是为懒人准备的。 SO_REUSEADDR 与 SO_REUSEPORT 是什么? TCP/UDP用五元组唯一标识一个连接。任...

品学楼A107 1514

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

从内核看SO_REUSEPORT的实现(基于5.9.9)

前言:SO_REUSEPORT是提高服务器性能的一个特性,从Linux3.9后支持,本文从内核5.9.9的源码分析SO_REUSEPORT的实现,因为内核源码非常复杂,尽量把自己的思路说一下。大家有兴趣的可以自己研究。 首先我们来看看SO_REUSEPORT是什么 SO_REUSEPORT (since Linux 3.9) Permits multiple AF_INET or AF_INET6 sockets to be bound to an

标子 的专栏 609

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Linux之SO_REUSEPORT属性笔记

以上就是SO_REUSEPORT属性的特点,实际使用中利用该属性结合其他相关的多路io高效机制特殊性,在实际使用中结合实际业务场景,从而实现高性能高可用的服务。

qq_26105397的博客 856

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Linux3.9中 SO_REUSEPORT 对高并发服务器的改进

背景 在传统网络编程模型中,为了实现高并发的服务器, 通常采用的做法是Master进程创建一个Listen socket,然后fork出来N个worker进程,这N个worker进程同时侦听这个socket。 然而这种模式仅仅是做到了进程级的可扩展性,即一个进程在忙时,其它进程可以介入帮忙处理,底层的socket句柄其实是同一个!简单点说,这是一个沙漏模型: 这种模型在处理同一个sock...

At the speed of ideas 758

so_reuseport linux,Linux 最新SO_REUSEPORT特性

1、前言昨天总结了一下Linux下网络编程“惊群”现象,给出Nginx处理惊群的方法,使用互斥锁。为例发挥多核的优势,目前常见的网络编程模型就是多进程或多线程,根据accpet的位置,分为如下场景:(1)单进程或线程创建socket,并进行listen和accept,接收到连接后创建进程和线程处理连接(2)单进程或线程创建socket,并进行listen,预先创建好多个工作进程或线程accept(...

weixin_42300113的博客 450

linux socket网络编程之SO_REUSEPORT

1、前言   昨天总结了一下Linux下网络编程“惊群”现象,给出Nginx处理惊群的方法,使用互斥锁。为例发挥多核的优势,目前常见的网络编程模型就是多进程或多线程,根据accpet的位置,分为如下场景:   (1)单进程或线程创建socket,并进行listen和accept,接收到连接后创建进程和线程处理连接   (2)单进程或线程创建socket,并进行listen,预先创建好多个工作进程或线程accept()在同一个服务器套接字、 这两种模型解...

随意的风的专栏 993

linux内核中的 哈希表_Linux 内核中 reuseport 的演进

(给Linux爱好者加星标,提升Linux技能)转自:187J3X1https://segmentfault.com/a/1190000020524323SO_REUSEPORT选项在Linux 3.9被引入内核,在这之前也有一个很像的选项SO_REUSEADDR。如果你不太清楚这两者的区别和联系,建议搜索 How do SO_REUSEADDR and SO_REUSEPORT di...

weixin_39870132的博客 282

java so reuseport_Linux 最新SO_REUSEPORT特性

1、前言昨天总结了一下Linux下网络编程“惊群”现象,给出Nginx处理惊群的方法,使用互斥锁。为例发挥多核的优势,目前常见的网络编程模型就是多进程或多线程,根据accpet的位置,分为如下场景:(1)单进程或线程创建socket,并进行listen和accept,接收到连接后创建进程和线程处理连接(2)单进程或线程创建socket,并进行listen,预先创建好多个工作进程或线程accept(...

weixin_42514970的博客 138

Linux下Netty实现高性能UDP服务(SO_REUSEPORT)

当UDP丢包的时候,我们正常情况下是增加各种缓冲区的大小,有调整内核缓冲区的,也有调整应用缓冲区的。但是还有另外一种方式,就是加速UDP数据包的处理速度。 1.当前Linux网络应用程序问题 运行在Linux系统上网络应用程序,为了利用多核的优势,一般使用以下比较典型的多进程/多线程服务器模型: 首先需要单线程listen一个端口上,然后由多个工作进程/线程去accept()在同一个服务器套接字上。 但有以下两个瓶颈: 单线程listener,在处理高速率海量连接时,一样会成为瓶颈 多线程访问serv.

代码时光 3452

终极解密:go-reuseport如何利用SO_REUSEADDR与SO_REUSEPORT实现端口复用

在网络编程中,端口复用是一项关键技术,尤其对于需要同时监听和拨号同一端口的场景(如TCP NAT打洞)至关重要。**go-reuseport** 是一个专为Go语言设计的库,通过封装底层系统调用,轻松实现TCP/UDP端口的复用功能。本文将深入解析其工作原理,帮助开发者快速掌握这一强大工具。 ## 什么是SO_REUSEADDR与SO_REUSEPORT? 在探讨 **go-reuseport

gitblog_00263的博客 829

Netty之ChannelOption的各种参数之EpollChannelOption.SO_REUSEPORT

socket选项 SO_REUSEPORT 转 miffa发布于 2015/03/24 17:21 字数 3383 阅读 6076 收藏6 点赞1 评论0 开发十年,就只剩下这套Java开发体系了 >>> 前言 本篇用于记录学习SO_REUSEPORT的笔记和心得,末尾还会提供一个...

weixin_30838873的博客 1324

Linux 中 reuseport 的演进

而当Client的SYN报文到达时,Server会首先根据本地端口(SYN报文的“)计算出一条hash冲突链,然后遍历该链表上的所有Socket,根据四元组匹配程度进行打分;举个栗子,假设内核有4条listening socket的hash冲突链,然后用户建立了4个Server:A、B、C、D,监听的地址和端口如下图所示,A和B使能了。,为上面的7个socket进行打分,而由于B监听的是精确的地址,所以B的得分会比A高,内核最终选择出一个SocketB进行后续处理。这一点Linux比BSD更加严格。

糯米导航 333
上一篇: Epoll在LT和ET模式下的读写方式
下一篇: 『APUE自学笔记』文件IO
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值