Nginx架构赏析

Nginx事件模型
Nginx采用了NIO的方式来处理请求,这是Nginx可以同时处理成千上万个请求的根本原因。想想低版本Tomcat的IO模型(高版本已支持NIO),每个请求会独占一个工作线程,当并发数上到几千时,就同时有几千的线程在处理请求了。这对操作系统来说,是个不小的挑战,线程带来的内存占用非常大,线程的上下文切换带来的cpu开销很大,自然性能就上不去了,而这些开销完全是没有意义的。

Nginx为什么要使用NIO呢?NIO到底是怎么回事呢?IO的本质就是读写事件,而当读写事件没有准备好时,必然不可操作,如果不用非阻塞的方式来调用,那就得阻塞调用了,事件没有准备好,那就只能等了,等事件准备好了,工作线程再继续吧。阻塞调用会进入内核等待,cpu就会让出去给别人用了,工作线程只能傻傻的睡觉等待,对单线程的worker来说,显然不合适,当网络事件越多时,大家都在等待呢,cpu空闲下来没人用,cpu利用率自然上不去了,更别谈高并发了。所以,为了高性能,必须使用NIO。关于NIO,我们这里就是一笔带过,想详细学习的同学可以去看我的NIO源码分析文章。

接下来,我们使用一段伪代码来总结一下Nginx的事件处理模型吧。

Date now; // 表示当前时间
while (true) {
// 处理任务队列里的所有任务
for task in tasks:
task.handler();

flushTime(now);	// 刷新当前时间
timeout = initValue; // 超时时间

// waitTasks可以理解为注册到epoll里的所有有效任务
for task in waitTasks: 
	// 列表里的第一个task的超时时间是最短的,如果它已经超时了,就调用超时处理函数
    if (task.time <= now) {	
        task.timeoutHandler();
    } else {
        // 更新超时时间
        timeout = t.time - now;
        break;
    }

// 通过epoll拿到已经就绪的事件
nevents = epoll(events, timeout);
// 挨个遍历处理事件
for i in nevents:
    Task task;
	// 读事件
    if (events[i].type == READ) {
        task.handler = readHandler;
    } else { // 写事件
        task.handler = writeHandler;
    }
	// 防到一个专门的执行队列里
    tasks(task);

}
USB Microphone https://www.soft-voice.com/
Wooden Speakers https://www.zeshuiplatform.com/
亚马逊测评 www.yisuping.cn
深圳网站建设www.sz886.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值