IO复用
首先用python演示普通worker的socket操作,是如何应对请求的?
![nginx的IO复用和epoll模型](http://p2.ttnews.xyz/loading.gif)
从上述代码可以看出worker进程一共进行了四步:
- accpet() 与客户端进行连接
- recv() 接收客户端发过来的数据
- send() 向客户端发送数据
- close() 关闭此次连接
经历这四步时,如果在recv()时,发生了IO堵塞,那么请求就会一直等待,直到close(),才会建立新连接。那么如何在IO阻塞时,也能处理其他客户的连接?
![nginx的IO复用和epoll模型](http://p2.ttnews.xyz/loading.gif)
以上代码演示了IO复用(多线程处理),这种方式解决了多个用户并发请求一个WEB网站,让每一个 socket复用完每个IO流的请求。nginx正是采取了这种方式,只是它的源码更复杂。
IO复用和epoll模型
在介绍nginx的epoll模型时,我们要先看一下传统IO多路复用模型的select和poll。
举个例子:有大量用户(100万个)同时与一个进程保持TCP连接,而在某一时刻只有少量(几十上百)是活跃的(即能接收数据包),那么在这一时刻只需处理这些少量请求即可!
传统select和poll:每次收集事件,都把这100万连接的套接字传给操作系统(用户态内存到内核内存的大量复制),而由操作系统内核寻找这些链接上没有处理的事件(浪费内存)。
epoll:将select和poll结合起,使用三步来操作。
- 调用epoll_creat建立一个epoll对象。
- 调用epoll_ctl向epoll对象中添加这100万个连接的套接字。
- 调用epoll_wait收集发生事件的连接。这是主要的步骤,将事件的连接放入一个链表,只要在链表中寻找发生连接的事件,不用去遍历这100万个连接。
总结
nginx正是采用了多路IO复用+epoll方式来应对高并发。以master控制多个worker,实现对多核CPU的利用。
閱讀更多 李老師tome 的文章