為什麼nginx效能比apache效能好
回複內容:
為什麼nginx效能比apache效能好
主要區別就是網路模型不同
apache->selectnginx->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/O5、非同步 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要差
Nginx主要使用了非同步無阻塞的IO減少了傳統阻塞模式下多線程的資源消耗和切換的開銷
另外從細節設計上比apache使用了更多的實用型的最佳化手段 相對來說 apache更中規中矩
最核心的區別在於apache是同步多進程模型,一個串連對應一個進程;nginx是非同步,多個串連(萬層級)可以對應一個進程
在linux下,apache依然是select,nginx可採用epoll,那麼:
apache 依然排隊處理
nginx 的epoll機制,來一個請求,扔給php-cgi,然後接著下一個請求。當php-cgi處理完了在返回給用戶端就行了。這樣就並行起來了。
樓主可以百度看看 epoll和select區別:
假設你在大學讀書,住的宿舍樓有很多間房間,你的朋友要來找你。
select版宿管大媽就會帶著你的朋友挨個房間去找,直到找到你為止。
而epoll版宿管大媽會先記下每位同學的房間號,你的朋友來時,只需告訴你的朋友你住在哪個房間即可,不用親內建著你的朋友滿大樓找人。
如果來了10000個人,都要找自己住這棟樓的同學時,select版和epoll版宿管大媽,誰的效率更高,不言自明。
同理,在高並發伺服器中,輪詢I/O是最耗時間的操作之一,select和epoll的效能誰的效能更高,同樣十分明了。