1、前言
昨天总结了一下Linux下网络编程“惊群”现象,给出Nginx处理惊群的方法,使用互斥锁。为例发挥多核的优势,目前常见的网络编程模型就是多进程或多线程,根据accpet的位置,分为如下场景:
(1)单进程或线程创建socket,并进行listen和accept,接收到连接后创建进程和线程处理连接
(2)单进程或线程创建socket,并进行listen,预先创建好多个工作进程或线程accept()在同一个服务器套接字、
这两种模型解充分发挥了多核CPU的优势,虽然可以做到线程和CPU核绑定,但都会存在:
单一listener工作进程胡线程在高速的连接接入处理时会成为瓶颈
多个线程之间竞争获取服务套接字
缓存行跳跃
很难做到CPU之间的负载均衡
随着核数的扩展,性能并没有随着提升
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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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
Atitit.linux&#160;内核&#160;新特性&#160;新功能
Atitit.linux 内核 新特性 新功能 1. Linux 3.2内核新特性 2012-02-12 22:41:471 1.1. EXT4:支持更大的块2 1.2. BTRFS:更快的数据清理 ...
SQL2043N 与 linux的randomize_va_space特性
自从数据库服务器从redhat4.6升级到redhat5.5之后,在使用TSM备份的时候偶尔会出现SQL2043N 查看错误: [db2inst1@limt ~]$ db2 ? SQL2043N S ...
linux的bash特性
Shell本身是应用程序,是用户与操作系统之间完成交互式操作的一个接口程序,为用户提供简化的操作. Bourne Again Shell,简称bash,是Linux系统中默认的shell程序. Bas ...
linux基础02-bash特性
Linux的行结束符是:[$] Windows的行结束符是:[$+回车] 目录管理:ls.cd.pwd.mkdir.rmdir.tree 文件管理:touch.stat.file.rm.cp.mv.n ...
linux bash基本特性
一.bash 基础特性 (1)命令历史的功能 history: 环境变量 HISTSIZE:命令历史记录的条数 HISTFILE: ~/.bash_history 每个用户都有自己独立的命令历史文件 ...
[转]linux最新分区方案
FROM : http://www.cnblogs.com/chenlulouis/archive/2009/08/27/1554983.html 我的服务器是500G.最重要的是/var分区一定要大 ...
支持 Windows 10 最新 PerMonitorV2 特性的 WPF 多屏高 DPI 应用开发
Windows 10 自 1703 开始引入第二代的多屏 DPI 机制(PerMonitor V2),而 WPF 框架可以支持此第二代的多屏 DPI 机制. 本文将介绍 WPF 框架利用第二代多屏 D ...
Linux bash基础特性二
shell脚本的组成部分 shebang 各种命令组合 编程变量种类 本地变量: 仅仅在当前的shell生效 环境变量: 在当前和子shell生效 局部变量: shell进程某代码片段 位置变量: $ ...
Linux bash基础特性一
命令别名 alias cdnet=”cd /etc/sysconfig/network-scripts” 针对用户的别名: “~/.bashrc” 针对系统的别名:”/etc/bashrc” 重读配置 ...
随机推荐
oracle 11g ORA-12541: TNS: 无监听程序 (DBD ERROR: OCIServerAttach)
From :http://www.cnblogs.com/wangyt223/archive/2012/12/11/2812931.html em无法浏览,同时监听起不来.同时他的监听服务还是正常的, ...
268. Missing Number
Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missin ...
Windows平台下为Python添加MySQL支持
到Python官网下载MySQL-python-1.2.5.win32-py2.7.exe 安装MySQL-python-1.2.5.win32-py2.7 附 64位MySQL-python下载地址 ...
转:JavaScript函数式编程(一)
转:JavaScript函数式编程(一) 一.引言 说到函数式编程,大家可能第一印象都是学院派的那些晦涩难懂的代码,充满了一大堆抽象的不知所云的符号,似乎只有大学里的计算机教授才会使用这些东西.在曾经 ...
C#,记录--一个方法中,完成对数据增删改操作
实际应用中,一般不会使用delete彻底的删除数据,大多都是逻辑删除 为了不把本文写成小作文,举个小栗子吧 表 A,deletestate为置删除字段,int类型,值为0和1 表中五条数据 查询 se ...
解决sublime text3 中文字符乱码
前言 由于系统编码问题导致的中文乱码解决,linux和windows解决方式都一样. 流程 linux下两步都需要,windows下只需要第二步. 1.在package install中搜索安装:co ...
python发送html格式的邮件
python发邮件 #!/usr/bin/python # -*- coding: UTF-8 -*- import smtplib from email.mime.text import MIMET ...
【摘】50个jQuery代码段帮助你成为一个更好的JavaScript开发者
今 天的帖子会给你们展示50个jQuery代码片段,这些代码能够给你的JavaScript项目提供帮助.其中的一些代码段是从jQuery1.4.2才 开始支持的做法,另一些则是真正有用的函数或方法,他 ...
ps查看CPU和内存占用前10的进程
内存增序 ps aux --sort rss 内存减序 ps aux --sort -rss cpu增序 ps auxw --sort=%cpu cpu减序 ps auxw --sort=-%cpu ...