nginx的IO複用和epoll模型

IO複用

首先用python演示普通worker的socket操作,是如何應對請求的?

nginx的IO複用和epoll模型

從上述代碼可以看出worker進程一共進行了四步:

  • accpet() 與客戶端進行連接
  • recv() 接收客戶端發過來的數據
  • send() 向客戶端發送數據
  • close() 關閉此次連接

經歷這四步時,如果在recv()時,發生了IO堵塞,那麼請求就會一直等待,直到close(),才會建立新連接。那麼如何在IO阻塞時,也能處理其他客戶的連接?

nginx的IO複用和epoll模型

以上代碼演示了IO複用(多線程處理),這種方式解決了多個用戶併發請求一個WEB網站,讓每一個 socket複用完每個IO流的請求。nginx正是採取了這種方式,只是它的源碼更復雜。

IO複用和epoll模型

在介紹nginx的epoll模型時,我們要先看一下傳統IO多路複用模型的select和poll。

舉個例子:有大量用戶(100萬個)同時與一個進程保持TCP連接,而在某一時刻只有少量(幾十上百)是活躍的(即能接收數據包),那麼在這一時刻只需處理這些少量請求即可!

傳統select和poll:每次收集事件,都把這100萬連接的套接字傳給操作系統(用戶態內存到內核內存的大量複製),而由操作系統內核尋找這些鏈接上沒有處理的事件(浪費內存)。

epoll:將select和poll結合起,使用三步來操作。

  1. 調用epoll_creat建立一個epoll對象。
  2. 調用epoll_ctl向epoll對象中添加這100萬個連接的套接字。
  3. 調用epoll_wait收集發生事件的連接。這是主要的步驟,將事件的連接放入一個鏈表,只要在鏈表中尋找發生連接的事件,不用去遍歷這100萬個連接。

總結

nginx正是採用了多路IO複用+epoll方式來應對高併發。以master控制多個worker,實現對多核CPU的利用。


分享到:


相關文章: