Nginx才短短几年,就拿下了Web服務器大壁江山,衆所周知,Nginx在處理大併發靜態請求方面,效率明顯高於Httpd,甚至能輕鬆解決C10K問題。php
在高併發鏈接的狀況下,Nginx是Apache服務器不錯的替代品。Nginx同時也能夠做爲7層負載均衡服務器來使用。根據個人測試結果,Nginx + PHP(FastCGI) 能夠承受3萬以上的併發鏈接數,至關於同等環境下Apache的10倍。html
通常來講,4GB內存的服務器+Apache(prefork模式)通常只能處理3000個併發鏈接,由於它們將佔用3GB以上的內存,還得爲系統預留1GB的內存。我曾經就有兩臺Apache服務器,由於在配置文件中設置的MaxClients爲4000,當Apache併發鏈接數達到3800時,致使服務器內存和Swap空間用滿而崩潰。java
而這臺 Nginx + PHP(FastCGI) 服務器在3萬併發鏈接下,開啓的10個Nginx進程消耗150M內存(15M*10=150M
),開啓的64個php-cgi進程消耗1280M內存(20M*64=1280M
),加上系統自身消耗的內存,總共消耗不到2GB內存。若是服務器內存較小,徹底能夠只開啓25個php-cgi進程,這樣php-cgi消耗的總內存數才500M。linux
在3萬併發鏈接下,訪問Nginx+ PHP(FastCGI) 服務器的PHP程序,仍然速度飛快。nginx
爲何Nginx在處理高併發方面要優於httpd,咱們先從兩種web服務器的工做原理以及工做模式提及。web
咱們都知道Apache有三種工做模塊,分別爲:prefork、worker、event。面試
若是不用「–with-mpm」顯式指定某種MPM,prefork就是Unix平臺上缺省的MPM。它所採用的預派生子進程方式也是 Apache1.3中採用的模式。spring
prefork自己並無使用到線程,2.0版使用它是爲了與1.3版保持兼容性;另外一方面,prefork用單獨的子進程來處理不一樣的請求,進程之間是彼此獨立的,這也使其成爲最穩定的MPM之一。apache
相對於prefork,worker是2.0版中全新的支持多線程和多進程混合模型的MPM。因爲使用線程來處理,因此能夠處理相對海量的請求,而系統資源的開銷要小於基於進程的服務器。數組
可是,worker也使用了多進程,每一個進程又生成多個線程,以得到基於進程服務器的穩定性,這種MPM的工做方 式將是Apache2.0的發展趨勢。
一個進程響應多個用戶請求,利用callback機制,讓套接字複用,請求過來後進程並不處理請求,而是直接交由其餘機制來處理,經過epoll機制來通知請求是否完成;在這個過程當中,進程自己一直處於空閒狀態,能夠一直接收用戶請求。能夠實現一個進程程響應多個用戶請求。支持持海量併發鏈接數,消耗更少的資源。
有幾個基本條件:
一、基於線程,即一個進程生成多個線程,每一個線程響應用戶的每一個請求。
二、基於事件的模型,一個進程處理多個請求,而且經過epoll機制來通知用戶請求完成。
三、基於磁盤的AIO(異步I/O)
四、支持mmap內存映射,mmap傳統的web服務器,進行頁面輸入時,都是將磁盤的頁面先輸入到內核緩存中,再由內核緩存中複製一份到web服務器上,mmap機制就是讓內核緩存與磁盤進行映射,web服務器,直接複製頁面內容便可。不須要先把磁盤的上的頁面先輸入到內核緩存去。
恰好,Nginx 支持以上全部特性。因此Nginx官網上說,Nginx支持50000併發,是有依據的。
傳統上基於進程或線程模型架構的Web服務經過每進程或每線程處理併發鏈接請求,這勢必會在網絡和I/O操做時產生阻塞,其另外一個必然結果則是對內存或CPU的利用率低下。
生成一個新的進程/線程須要事先備好其運行時環境,這包括爲其分配堆內存和棧內存,以及爲其建立新的執行上下文等。這些操做都須要佔用CPU,並且過多的進程/線程還會帶來線程抖動或頻繁的上下文切換,系統性能也會由此進一步降低。
另外一種高性能web服務器/Web服務器反向代理:Nginx,Nginx的主要着眼點就是其高性能以及對物理計算資源的高密度利用,所以其採用了不一樣的架構模型。受啓發於多種操做系統設計中基於「事件」的高級處理機制,Nginx採用了模塊化、事件驅動、異步、單線程及非阻塞的架構,並大量採用了多路複用及事件通知機制。
在Nginx中,鏈接請求由爲數很少的幾個僅包含一個線程的進程Worker以高效的迴環(run-loop)機制進行處理,而每一個Worker能夠並行處理數千個的併發鏈接及請求。
Nginx會按需同時運行多個進程:一個主進程(master)和幾個工做進程(worker),配置了緩存時還會有緩存加載器進程(cache loader)和緩存管理器進程(cache manager)等。全部進程均是僅含有一個線程,並主要經過「共享內存」的機制實現進程間通訊。主進程以root用戶身份運行,而worker、cache loader和cache manager均應以非特權用戶身份運行。
在高鏈接併發的狀況下,Nginx是Apache服務器不錯的替代品。
Nginx 安裝很是的簡單 , 配置文件很是簡潔(還可以支持perl語法),Bugs 很是少的服務器: Nginx 啓動特別容易, 而且幾乎能夠作到7*24不間斷運行,即便運行數個月也不須要從新啓動. 你還可以 不間斷服務的狀況下進行軟件版本的升級 。
最後咱們從各自使用的多路複用IO模型來分析:
單個進程可以 監視的文件描述符的數量存在最大限制;
select()所維護的 存儲大量文件描述符的數據結構 ,隨着文件描述符數量的增加,其在用戶態和內核的地址空間的複製所引起的開銷也會線性增加;
因爲網絡響應時間的延遲使得大量TCP鏈接處於非活躍狀態,但調用select()仍是會對 全部的socket進行一次線性掃描 ,會形成必定的開銷;
epoll帶來了兩個優點,大幅度提高了性能:
1)基於事件的就緒通知方式 ,select/poll方式,進程只有在調用必定的方法後,內核纔會對全部監視的文件描述符進行掃描,而epoll事件經過epoll_ctl()註冊一個文件描述符,一旦某個文件描述符就緒時,內核會採用相似call back的回調機制,迅速激活這個文件描述符,epoll_wait()便會獲得通知
2)調用一次epoll_wait()得到就緒文件描述符時,返回的並非實際的描述符,而是一個表明就緒描述符數量的值,拿到這些值去epoll指定的一個數組中依次取得相應數量的文件描述符便可,這裏使用內存映射(mmap)技術, 避免了複製大量文件描述符帶來的開銷
3)固然epoll也有必定的侷限性, epoll只有Linux2.6纔有實現 ,而其餘平臺都沒有,這和apache這種優秀的跨平臺服務器,顯然是有些背道而馳了。
4)簡單來講epoll是select的升級版,單進程管理的文件描述符沒有最大限制。但epoll只有linux平臺可以使用。做爲跨平臺的Apache沒有使用
來源:http://codebay.cn/post/8557.html
近期熱文推薦:
1.600+ 道 Java面試題及答案整理(2021最新版)
2.終於靠開源項目弄到 IntelliJ IDEA 激活碼了,真香!
3.阿里 Mock 工具正式開源,幹掉市面上全部 Mock 工具!
4.Spring Cloud 2020.0.0 正式發佈,全新顛覆性版本!
以爲不錯,別忘了隨手點贊+轉發哦!