為什么nginx性能比apache性能好


為什么nginx性能比apache性能好

  • nginx用的相對於c++更底層的c編寫,有一定原因
  • 兩種webserver的設計和定位的不同。
  • nginx自身定位為一個輕量級webserver,高級功能依賴於配置和加載模塊組建。而apache自身功能強大,自身設計也是追求強大的穩定性。
  • 同時最核心原因是二者網絡IO處理的方式,nginx是異步非阻塞,而apache是同步阻塞,這也是保障了nginx高性能和apache高穩定性的原因。

主要區別就是網絡模型不同

apache->select
nginx->epoll (主要用這個)

簡介
select,epoll都是IO多路復用的機制。I/O多路復用就通過一種機制,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程序進行相應的讀寫操作。但select,epoll本質上都是同步I/O,因為他們都需要在讀寫事件就緒后自己負責進行讀寫,也就是說這個讀寫過程是阻塞的
  • I/O模式
1、阻塞 I/O:(Linux下的I/O操作默認是阻塞I/O)
2、非阻塞 I/O:(可以通過fcntl或者open時使用O_NONBLOCK參數,將fd設置為非阻塞的I/O)
3、I/O 多路復用:(I/O多路復用,通常需要非阻塞I/O配合使用)
4、信號驅動 I/O
5、異步 I/O
  • select缺點:
    1、每次調用select,都需要把fd集合從用戶態拷貝到內核態,這個開銷在fd很多時會很大
    2、每次調用select都需要在內核遍歷傳遞進來的所有fd,這個開銷在fd很多時也很大
    3、select支持的文件描述符數量太小了,默認是1024
  • epoll
    epoll是對select的改進,可以避免上述的三個缺點,我們先看一下epoll和select的調用接口上的不同。
    select只提供了一個函數select,epoll提供了三個函數
epoll_create:創建一個epoll句柄
epoll_ctl:注冊要監聽的事件類型
epoll_wait:等待事件的產生

對於1:epoll的解決方案在epoll_ctl函數中。每次注冊新的事件到epoll句柄中時(在epoll_ctl中指定EPOLL_CTL_ADD),會把所有的fd拷貝進內核,而不是在epoll_wait的時候重復拷貝,epoll保證了每個fd在整個過程中只會拷貝一次。

對於2:epoll的解決方案不像select那樣每次都把current輪流加入fd對應的設備等待隊列中,而只在epoll_ctl時把current掛一遍(這一遍必不可少)並為每個fd指定一個回調函數,當設備就緒,喚醒等待隊列上的等待者時,就會調用這個回調函數,而這個回調函數會把就緒的fd加入一個就緒鏈表)。epoll_wait的工作實際上就是在這個就緒鏈表中查看有沒有就緒的fd(利用schedule_timeout()實現睡一會,判斷一會的效果,和select實現是類似的)。

對於3:epoll沒有這個限制,它所支持的FD上限是最大可以打開文件的數目,這個數字一般遠大於2048,舉個例子,在1GB內存的機器上大約是10萬左右,具體數目可以cat /proc/sys/fs/file-max察看,一般來說這個數目和系統內存關系很大。

  • epoll的優點

1、監視的描述符數量不受限制,select的最大缺點就是進程打開的fd是有數量限制的。這對於連接數量比較大的服務器來說根本不能滿足。雖然也可以選擇多進程的解決方案,不過雖然linux上面創建進程的代價比較小,但仍舊是不可忽視的,加上進程間數據同步遠比不上線程間同步的高效,所以也不是一種完美的方案。

2、IO的效率不會隨着監視fd的數量的增長而下降。epoll不同於select輪詢的方式,而是通過每個fd定義的回調函數來實現的,只有就緒的fd才會執行回調函數。

3、支持電平觸發和邊沿觸發(只告訴進程哪些文件描述符剛剛變為就緒狀態,它只說一遍,如果我們沒有采取行動,那么它將不會再次告知,這種方式稱為邊緣觸發)兩種方式,理論上邊緣觸發的性能要更高一些,但是代碼實現相當復雜。

總結:
  1. select實現需要自己不斷輪詢所有fd集合,直到設備就緒,期間可能要睡眠和喚醒多次交替。而epoll其實也需要調用epoll_wait不斷輪詢就緒鏈表,期間也可能多次睡眠和喚醒交替,但是它是設備就緒時,調用回調函數,把就緒fd放入就緒鏈表中,並喚醒在epoll_wait中進入睡眠的進程。雖然都要睡眠和交替,但是select和poll在“醒着”的時候要遍歷整個fd集合,而epoll在“醒着”的時候只要判斷一下就緒鏈表是否為空就行了,這節省了大量的CPU時間。這就是回調機制帶來的性能提升。

  2. select每次調用都要把fd集合從用戶態往內核態拷貝一次,並且要把current往設備等待隊列中掛一次,而epoll只要一次拷貝,而且把current往等待隊列上掛也只掛一次(在epoll_wait的開始,注意這里的等待隊列並不是設備等待隊列,只是一個epoll內部定義的等待隊列)。這也能節省不少的開銷。

  3. 在 select中,進程只有在調用一定的方法后,內核才對所有監視的文件描述符進行掃描,而epoll事先通過epoll_ctl()來注冊一 個文件描述符,一旦基於某個文件描述符就緒時,內核會采用類似callback的回調機制,迅速激活這個文件描述符,當進程調用epoll_wait() 時便得到通知。

  4. mmap加速內核與用戶空間的信息傳遞。epoll是通過內核於用戶空間mmap同一塊內存,避免了無畏的內存拷貝。

所以嗎,效率就看出來了,不過nginx在穩定性上比apache要差


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM