Nginx中的C10K問題和事件驅動模型

C10K問題

在傳統的同步阻塞處理模型中,當創建的進程或線程過多時,緩存I/O、內核將數據拷貝到用戶進程空間、阻塞,進程/線程上下文切換消耗大,簡而言之 ,C10K問題就是無法同時處理大量客戶端(10,000)的網絡套接字。

解決思路

  1. 每個連接創建一個進程或線程
  2. 一個進程或線程同時處理多個連接

多線程處理多連接

申請和管理多線程需要佔用額外資源,擴展性差,如tomcat。

單線程處理多連接

select方式:使用fd_set結構體告訴內核同時監控那些文件句柄,使用逐個排查方式去檢查是否有文件句柄就緒或者超時。該方式有以下缺點:文件句柄數量是有上線的,逐個檢查吞吐量低,每次調用都要重複初始化fd_set。

poll方式:該方式主要解決了select方式的2個缺點,文件句柄上限問題(鏈表方式存儲)以及重複初始化問題(不同字段標註關注事件和發生事件),但是逐個去檢查文件句柄是否就緒的問題仍然沒有解決。

epoll方式:該方式可以說是C10K問題的killer,他不去輪詢監聽所有文件句柄是否已經就緒。epoll只對發生變化的文件句柄感興趣。其工作機制是,使用"事件"的就緒通知方式,通過epoll_ctl註冊文件描述符fd,一旦該fd就緒,內核就會採用類似callback的回調機制來激活該fd, epoll_wait便可以收到通知, 並通知應用程序。而且epoll使用一個文件描述符管理多個描述符,將用戶進程的文件描述符的事件存放到內核的一個事件表中, 這樣數據只需要從內核緩存空間拷貝一次到用戶進程地址空間。而且epoll是通過內核與用戶空間共享內存方式來實現事件就緒消息傳遞的,其效率非常高,但是epoll是依賴系統的(Linux)。

Nginx中支持的事件驅動模型

kqueue | rtsig | epoll | /dev/poll | select | poll | eventport

標準事件模型

Select、poll屬於標準事件模型,如果當前系統不存在更有效的方法,nginx會選擇select或poll。

高級事件模型

/dev/poll適用於 Solaris 7 11/99+, HP/UX 11.22+ (eventport), IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+;

Eventport適用於 Solaris 10. 爲了防止出現內核崩潰的問題, 有必要安裝安全補丁;

Kqueue適用用於 FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X,使用雙處理器的MacOS X系統使用kqueue可能會造成內核崩潰;

epoll適用於於Linux內核2.6版本及以後的系統。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章