阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

为什么Nginx的性能要比Apache高很多?

377次阅读
没有评论

共计 4089 个字符,预计需要花费 11 分钟才能阅读完成。

为什么 Nginx 的性能要比 Apache 高很多?这得益于 Nginx 使用了最新的 epoll(Linux 2.6 内核)和 kqueue(freebsd)网络 I / O 模型,而 Apache 则使用的是传统的 select 模型。

目前 Linux 下能够承受高并发访问的 Squid、Memcached 都采用的是 epoll 网络 I / O 模型。

处理大量的连接的读写,Apache 所采用的 select 网络 I / O 模型非常低效。

下面用一个比喻来解析 Apache 采用的 select 模型和 Nginx 采用的 epoll 模型进行之间的区别:

假设你在大学读书,住的宿舍楼有很多间房间,你的朋友要来找你。

select 版宿管大妈就会带着你的朋友挨个房间去找,直到找到你为止。

而 epoll 版宿管大妈会先记下每位同学的房间号,

你的朋友来时,只需告诉你的朋友你住在哪个房间即可,不用亲自带着你的朋友满大楼找人。

如果来了 10000 个人,都要找自己住这栋楼的同学时,select 版和 epoll 版宿管大妈,谁的效率更高,不言自明。

同理,在高并发服务器中,轮询 I / O 是最耗时间的操作之一,select 和 epoll 的性能谁的性能更高,同样十分明了。

?
1
epoll - I/O event notification facility

在 linux 的网络编程中,很长的时间都在使用 select 来做事件触发。

在 linux 新的内核中,有了一种替换它的机制,就是 epoll。

相比于 select,epoll 最大的好处在于它不会随着监听 fd 数目的增长而降低效率。

因为在内核中的 select 实现中,它是采用轮询来处理的,轮询的 fd 数目越多,自然耗时越多。

并且,在 linux/posix_types.h 头文件有这样的声明:

1
#define __FD_SETSIZE    1024

表示 select 最多同时监听 1024 个 fd,当然,可以通过修改头文件再重编译内核来扩大这个数目,但这似乎并不治本。

epoll 的接口非常简单,一共就三个函数:

1. int epoll_create(int size);

创建一个 epoll 的句柄,size 用来告诉内核这个监听的数目一共有多大。

这个参数不同于 select()中的第一个参数,给出最大监听的 fd+ 1 的值。

需要注意的是,当创建好 epoll 句柄后,它就是会占用一个 fd 值,在 linux 下如果查看 /proc/ 进程 id/fd/,

是能够看到这个 fd 的,所以在使用完 epoll 后,必须调用 close()关闭,否则可能导致 fd 被耗尽。

2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

epoll 的事件注册函数,它不同与 select()是在监听事件时告诉内核要监听什么类型的事件,

而是在这里先注册要监听的事件类型。第一个参数是 epoll_create()的返回值,

第二个参数表示动作,用三个宏来表示:

EPOLL_CTL_ADD:注册新的 fd 到 epfd 中;

EPOLL_CTL_MOD:修改已经注册的 fd 的监听事件;

EPOLL_CTL_DEL:从 epfd 中删除一个 fd;

第三个参数是需要监听的 fd,第四个参数是告诉内核需要监听什么事,struct epoll_event 结构如下:

1
2
3
4
5
6
7
8
9
10
typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;
struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};

events 可以是以下几个宏的集合:

EPOLLIN:表示对应的文件描述符可以读(包括对端 SOCKET 正常关闭);

EPOLLOUT:表示对应的文件描述符可以写;

EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);

EPOLLERR:表示对应的文件描述符发生错误;

EPOLLHUP:表示对应的文件描述符被挂断;

EPOLLET:将 EPOLL 设为边缘触发 (Edge Triggered) 模式,这是相对于水平触发 (Level Triggered) 来说的。

EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,

如果还需要继续监听这个 socket 的话,需要再次把这个 socket 加入到 EPOLL 队列里

3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

等待事件的产生,类似于 select()调用。

参数 events 用来从内核得到事件的集合,maxevents 告之内核这个 events 有多大,这个 maxevents 的值不能大于创建 epoll_create()时的 size,参数 timeout 是超时时间(毫秒,0 会立即返回,- 1 将不确定,也有说法说是永久阻塞)。

该函数返回需要处理的事件数目,如返回 0 表示已超时。

4、关于 ET、LT 两种工作模式:

可以得出这样的结论:

ET 模式仅当状态发生变化的时候才获得通知, 这里所谓的状态的变化并不包括缓冲区中还有未处理的数据,也就是说, 如果要采用 ET 模式, 需要一直 read/write 直到出错为止,很多人反映为什么采用 ET 模式只接收了一部分数据就再也得不到通知了,大多因为这样;而 LT 模式是只要有数据没有处理就会一直通知下去的。

那么究竟如何来使用 epoll 呢?其实非常简单。

通过在包含一个头文件 #include <sys/epoll.h> 以及几个简单的 API 将可以大大的提高你的网络服务器的支持人数。

首先通过 create_epoll(int maxfds)来创建一个 epoll 的句柄,其中 maxfds 为你 epoll 所支持的最大句柄数。

这个函数会返回一个新的 epoll 句柄,之后的所有操作将通过这个句柄来进行操作。

在用完之后,记得用 close()来关闭这个创建出来的 epoll 句柄。

之后在你的网络主循环里面,每一帧的调用 epoll_wait(int epfd, epoll_event events, int max events, int timeout)来查询所有的网络接口,看哪一个可以读,哪一个可以写了。基本的语法为:

nfds = epoll_wait(kdpfd, events, maxevents, -1);

其中 kdpfd 为用 epoll_create 创建之后的句柄,events 是一个 epoll_event* 的指针,当 epoll_wait 这个函数操作成功之后,epoll_events 里面将储存所有的读写事件。

max_events 是当前需要监听的所有 socket 句柄数。最后一个 timeout 是 epoll_wait 的超时,为 0 的时候表示马上返回,为 - 1 的时候表示一直等下去,直到有事件范围,为任意正整数的时候表示等这么长的时间,如果一直没有事件,则范围。一般如果网络主循环是单独的线程的话,可以用 - 1 来等,这样可以保证一些效率,如果是和主逻辑在同一个线程的话,则可以用 0 来保证主循环的效率。

epoll_wait 范围之后应该是一个循环,遍利所有的事件。

几乎所有的 epoll 程序都使用下面的框架:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
for(; ;)
    {
        nfds = epoll_wait(epfd,events,20,500);
        for(i=0;i<nfds;++i)
        {
            if(events[i].data.fd==listenfd) //有新的连接
            {
                connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen); //accept这个连接
                ev.data.fd=connfd;
                ev.events=EPOLLIN|EPOLLET;
                epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); //将新的 fd 添加到 epoll 的监听队列中
            }
            else if(events[i].events&EPOLLIN ) //接收到数据,读 socket
            {
                n = read(sockfd, line, MAXLINE)) < 0    //
                ev.data.ptr = md;    //md为自定义类型,添加数据
                ev.events=EPOLLOUT|EPOLLET;
                epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);//修改标识符,等待下一个循环时发送数据,异步处理的精髓
            }
            else if(events[i].events&EPOLLOUT) //有数据待发送,写 socket
            {
                struct myepoll_data* md = (myepoll_data*)events[i].data.ptr;    //取数据
                sockfd = md->fd;
                send(sockfd, md->ptr, strlen((char*)md->ptr), 0 );        //发送数据
                ev.data.fd=sockfd;
                ev.events=EPOLLIN|EPOLLET;
                epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); //修改标识符,等待下一个循环时接收数据
            }
            else
            {
                //其他的处理
            }
        }
    }

本文永久更新链接地址:http://www.linuxidc.com/Linux/2015-05/117797.htm

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-20发表,共计4089字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19350
评论数
4
阅读量
7963602
文章搜索
热门文章
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛 NAS 中安装 Navidrome 音乐文件中文标签乱码问题解决、安装 FntermX 终端 问题背景 ...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
150元打造低成本NAS小钢炮,捡一块3865U工控板

150元打造低成本NAS小钢炮,捡一块3865U工控板

150 元打造低成本 NAS 小钢炮,捡一块 3865U 工控板 一块二手的熊猫 B3 工控板 3865U,搭...
仅2MB大小!开源硬件监控工具:Win11 无缝适配,CPU、GPU、网速全维度掌控

仅2MB大小!开源硬件监控工具:Win11 无缝适配,CPU、GPU、网速全维度掌控

还在忍受动辄数百兆的“全家桶”监控软件?后台偷占资源、界面杂乱冗余,想查个 CPU 温度都要层层点选? 今天给...
零成本上线!用 Hugging Face免费服务器+Docker 快速部署HertzBeat 监控平台

零成本上线!用 Hugging Face免费服务器+Docker 快速部署HertzBeat 监控平台

零成本上线!用 Hugging Face 免费服务器 +Docker 快速部署 HertzBeat 监控平台 ...
星哥带你玩飞牛NAS-11:咪咕视频订阅部署全攻略

星哥带你玩飞牛NAS-11:咪咕视频订阅部署全攻略

星哥带你玩飞牛 NAS-11:咪咕视频订阅部署全攻略 前言 在家庭影音系统里,NAS 不仅是存储中心,更是内容...
4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

  4 盘位、4K 输出、J3455、遥控,NAS 硬件入门性价比之王 开篇 在 NAS 市场中,威...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
告别Notion焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁”

告别Notion焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁”

  告别 Notion 焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁” 引言 在数字笔记工...
12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换,告别多工具切换

12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换,告别多工具切换

12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换...
浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍

浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍

浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍 前言 在 AI 自动化快速发展的当下,浏览器早已不再只是...
4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

  4 盘位、4K 输出、J3455、遥控,NAS 硬件入门性价比之王 开篇 在 NAS 市场中,威...
星哥带你玩飞牛NAS硬件03:五盘位+N5105+双网口的成品NAS值得入手吗

星哥带你玩飞牛NAS硬件03:五盘位+N5105+双网口的成品NAS值得入手吗

星哥带你玩飞牛 NAS 硬件 03:五盘位 +N5105+ 双网口的成品 NAS 值得入手吗 前言 大家好,我...