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,并且保证唤醒的均衡性。

3、测试代码

 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, );
assert(listenfd >= ); int val =;
/*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 != -); ret = listen(listenfd, );
assert(ret != -);
while () {
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 != -) {
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 ;
} int main()
{
int i = ;
for (i = ; i < WORKER; i++) {
printf("Create worker %d\n", i);
pid_t pid = fork();
/*child process */
if (pid == ) {
worker(i);
}
if (pid < ) {
printf("fork error");
}
}
/*wait child process*/
while (wait(NULL) != )
;
if (errno == ECHILD) {
fprintf(stderr, "wait error:%s\n", strerror(errno));
}
return ;
}

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

测试结果如下所示:

从结果可以看出,四个进程监听相同的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

Linux 最新SO_REUSEPORT特性的更多相关文章

  1. Atitit.linux 内核 新特性 新功能

    Atitit.linux 内核 新特性 新功能 1.  Linux 3.2内核新特性 2012-02-12 22:41:471 1.1. EXT4:支持更大的块2 1.2. BTRFS:更快的数据清理 ...

  2. SQL2043N 与 linux的randomize_va_space特性

    自从数据库服务器从redhat4.6升级到redhat5.5之后,在使用TSM备份的时候偶尔会出现SQL2043N  查看错误: [db2inst1@limt ~]$ db2 ? SQL2043N S ...

  3. linux的bash特性

    Shell本身是应用程序,是用户与操作系统之间完成交互式操作的一个接口程序,为用户提供简化的操作. Bourne Again Shell,简称bash,是Linux系统中默认的shell程序. Bas ...

  4. XCTF-ics-07(floatval函数特性+Linux目录结构特性)

    直接进入到项目管理页面,给了三段源码. 第一段 <?php session_start(); if (!isset($_GET[page])) { show_source(__FILE__); ...

  5. linux基础02-bash特性

    Linux的行结束符是:[$] Windows的行结束符是:[$+回车] 目录管理:ls.cd.pwd.mkdir.rmdir.tree 文件管理:touch.stat.file.rm.cp.mv.n ...

  6. linux bash基本特性

    一.bash 基础特性 (1)命令历史的功能 history: 环境变量 HISTSIZE:命令历史记录的条数 HISTFILE: ~/.bash_history 每个用户都有自己独立的命令历史文件 ...

  7. [转]linux最新分区方案

    FROM : http://www.cnblogs.com/chenlulouis/archive/2009/08/27/1554983.html 我的服务器是500G.最重要的是/var分区一定要大 ...

  8. 支持 Windows 10 最新 PerMonitorV2 特性的 WPF 多屏高 DPI 应用开发

    Windows 10 自 1703 开始引入第二代的多屏 DPI 机制(PerMonitor V2),而 WPF 框架可以支持此第二代的多屏 DPI 机制. 本文将介绍 WPF 框架利用第二代多屏 D ...

  9. linux服务器市场特性高可用高性能 (集群上体现)安全

    https://www.linuxprobe.com/chapter-00.html 1 linux安全 更安全 对比windows  代码漏洞 及时修补 全世界看到源代码 2 linux 可以卸载图 ...

随机推荐

  1. shop_list

    #!/usr/bin/env python # -*- coding: utf-8 -*- #输出商品列表,用户输入序号,显示用户选中的商品 li = ["手机", "电 ...

  2. Java:构造器,构造代码块,静态代码块的执行顺序

    1.构造器:与类同名且没有返回值,用来初始化类属性: 构造器又分为无参构造器和有参构造器 1.1:无参构造器 public class Contruction{ ...属性... public Con ...

  3. Python 与 C/C++ 交互的几种方式

    python作为一门脚本语言,其好处是语法简单,很多东西都已经封装好了,直接拿过来用就行,所以实现同样一个功能,用Python写要比用C/C++代码量会少得多.但是优点也必然也伴随着缺点(这是肯定的, ...

  4. python课程第一天笔记-la

    http://www.cnblogs.com/onda/   ----------------------20170423 一:Cpython  pypy 区别 等;Cpython 是一行一行解释, ...

  5. 关于股票最佳买卖时机的lintcode代码

    class Solution {public:    /**     * @param prices: Given an integer array     * @return: Maximum pr ...

  6. PAT1028. List Sorting (25)---strcmp

    题目链接为:https://www.patest.cn/contests/pat-a-practise/1028 1028. List Sorting (25) Excel can sort reco ...

  7. 用ArrayList(解决约瑟夫问题)

    约瑟夫问题(Josephus problem)又称为约瑟夫斯置换,是一个出现在计算机科学和数学中的问题.在计算机编程的算法中,约瑟夫问题类似问题又称为约瑟夫环."丢手绢问题". 据 ...

  8. vs2015c++/MFC入门知识全集/实例规范书籍视频下载孙鑫c++对话框计算器基础控件使用教程系列

    VIP教程可免费看.可免费下载前部分试看教程地址:http://dwz.cn/4PcfPk免费下载地址:http://dwz.cn/mfc888 本课程目录 67章 [MFC项目开发第01天]Wind ...

  9. Microsoft Windows 2003 SP2 - 'ERRATICGOPHER' SMB Remote Code Execution

    EDB-ID: 41929 Author: vportal Published: 2017-04-25 CVE: N/A Type: Remote Platform: Windows Aliases: ...

  10. 连锁反应confirm

    <script> function del(){ var flag = confirm("你真要删除么?"); if( flag ){ alert("我已被你 ...