系统相关
首页 > 系统相关> > Nginx架构赏析

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

标签:www,task,架构,NIO,Nginx,线程,cpu,赏析
来源: https://blog.csdn.net/weixin_45032957/article/details/115395139