Nginx基本模塊:
Nginx 默認(rèn)采用守護(hù)模式啟動(dòng)贵涵,守護(hù)模式讓master進(jìn)程啟動(dòng)后在后臺(tái)運(yùn)行宾茂。在Nginx運(yùn)行期間主要由一個(gè)master主進(jìn)程和多個(gè)worker進(jìn)程
worker進(jìn)程數(shù)目建議設(shè)為與cpu核數(shù)相同跨晴,這樣每個(gè)worker進(jìn)程都綁定特定的CPU核心端盆,進(jìn)程間切換的代價(jià)是最小的焕妙。因?yàn)橐皇荖ginx一般做的是高并發(fā)代理弓摘,基本沒(méi)有IO操作,大多數(shù)都是CPU密集型操作末患,很少出現(xiàn)IO阻塞等情況璧针。二是進(jìn)程與CPU調(diào)度的關(guān)系,單個(gè)核心處理多個(gè)進(jìn)程的時(shí)候渤昌,是排隊(duì)處理的独柑,如果設(shè)置多個(gè)進(jìn)程的時(shí)候忌栅,是排隊(duì)處理的曲稼,如果設(shè)置多個(gè)進(jìn)程時(shí),會(huì)帶來(lái)進(jìn)程間切換的開(kāi)銷
master進(jìn)程不會(huì)對(duì)用戶請(qǐng)求提供服務(wù)瑞驱,只用于管理真正提供服務(wù)的worker進(jìn)程唤反,所以master進(jìn)程可以是唯一的鸭津,它僅專注于自己的純管理工作逆趋,為管理員提供命令行服務(wù)闻书,包括諸如啟動(dòng)服務(wù)魄眉、停止服務(wù)、重載配置文件楞卡、平滑升級(jí)程序等蒋腮,當(dāng)任意一個(gè)worker進(jìn)程出現(xiàn)錯(cuò)誤從而導(dǎo)致coredump時(shí),master進(jìn)程會(huì)立刻啟動(dòng)新的worker進(jìn)程繼續(xù)服務(wù)焦除。
-
網(wǎng)絡(luò)請(qǐng)求的處理膘魄,是放在worker進(jìn)程中來(lái)完成的竭讳,而且只能在一個(gè)worker進(jìn)程中處理绢慢。多個(gè)worker進(jìn)程是相互獨(dú)立且對(duì)等競(jìng)爭(zhēng)的。
采用這種方式的好處:- 節(jié)省鎖帶來(lái)的開(kāi)銷骚露。對(duì)于每個(gè)worker進(jìn)程來(lái)說(shuō)棘幸,獨(dú)立的進(jìn)程误续,不需要加鎖女嘲,所以省掉了鎖帶來(lái)的開(kāi)銷诞帐,同時(shí)在編程以及問(wèn)題查上時(shí)停蕉,也會(huì)方便很多
- 獨(dú)立進(jìn)程慧起,減少風(fēng)險(xiǎn)蚓挤。
采用獨(dú)立的進(jìn)程灿意,可以讓互相之間不會(huì)影響缤剧,當(dāng)一個(gè)worker進(jìn)程異常退出時(shí)荒辕,其它進(jìn)程還在工作抵窒,服務(wù)不會(huì)中斷李皇,master進(jìn)程則很快重新啟動(dòng)新的worker進(jìn)程。雖然當(dāng)前worker上的所有請(qǐng)求失敗付材,不過(guò)不會(huì)影響到所有請(qǐng)求厌衔,所以降低了風(fēng)險(xiǎn)富寿。
- 每個(gè)worker里面只有一個(gè)主線程页徐,但一個(gè)worker可以同時(shí)處理多個(gè)請(qǐng)求变勇。nginx采取異步非阻塞的方式處理請(qǐng)求搀绣,每個(gè)請(qǐng)求進(jìn)來(lái)链患,worker線程將其注冊(cè)處理轉(zhuǎn)發(fā)給下游服務(wù)(如php-fpm)后麻捻,并不是掛起等待,而是切換處理別的請(qǐng)求巷折。采用這種輪詢的方式來(lái)并發(fā)處理大量請(qǐng)求
nginx的處理流程
Nginx的IO通常使用epoll,epoll函數(shù)使用了I/O復(fù)用模型署拟。與I/O阻塞模型比較歌豺,I/O復(fù)用模型的優(yōu)勢(shì)在于可以同時(shí)等待多個(gè)(而不只是一個(gè))套接字描述符就緒馒铃。Nginx的epoll工作流程如下:
- 首先区宇,master 進(jìn)程接受到信號(hào)(如nginx -s reload)后啟動(dòng),讀取配置文件值戳,建好需要listen的socket后议谷,然后再fork出多個(gè)woker進(jìn)程,這樣每個(gè)work進(jìn)程都可以去accept這個(gè)socket
2 . 當(dāng)一個(gè)client連接到來(lái)時(shí)堕虹,所有accept的work進(jìn)程都會(huì)受到通知卧晓,但只有一個(gè)進(jìn)程可以accept成功,其它的則會(huì)accept失敗赴捞,Nginx提供了一把共享鎖accept_mutex來(lái)保證同一時(shí)刻只有一個(gè)work進(jìn)程在accept連接逼裆,從而解決驚群?jiǎn)栴}
當(dāng)一個(gè)worker進(jìn)程accept這個(gè)連接后,就開(kāi)始讀取請(qǐng)求赦政,解析請(qǐng)求胜宇,處理請(qǐng)求昼钻,產(chǎn)生數(shù)據(jù)后狈究,再返回給客戶端碎罚,最后才斷開(kāi)連接竟趾,這樣一個(gè)完成的請(qǐng)求就結(jié)束了
一個(gè)worker進(jìn)程可以同時(shí)處理多個(gè)請(qǐng)求,每個(gè)worker進(jìn)程只有一個(gè)主線程,而是采用異步非阻塞的方式來(lái)處理并發(fā)請(qǐng)求。比如同時(shí)有多個(gè)http request的時(shí)候,worker主線程與第一條request建議連接將其處理轉(zhuǎn)發(fā)給下游fast cgi后,并不會(huì)掛起等待波丰,而是立馬處理下一條纫骑,可以理解輪詢處理煤墙。與多線程相比铣减,這種事件處理方式是有很大的優(yōu)勢(shì)的劣针,不需要?jiǎng)?chuàng)建線程,每個(gè)請(qǐng)求占用的內(nèi)存也很少,沒(méi)有上下文切換,事件處理非常的輕量級(jí)。并發(fā)數(shù)再多也不會(huì)導(dǎo)致無(wú)謂的資源浪費(fèi)(上下文切換),更多的并發(fā)數(shù),只是會(huì)占用更多的內(nèi)存而已枣申。因此nginx 是非常適合處理高并發(fā)請(qǐng)求的
驚群現(xiàn)象
驚群現(xiàn)象:驚群效應(yīng)就是當(dāng)一個(gè)fd的事件被觸發(fā)時(shí)像寒,所有等待這個(gè)fd的線程或進(jìn)程都被喚醒祭芦。一般都是socket的accept()會(huì)導(dǎo)致驚群,很多個(gè)進(jìn)程都block在server socket的accept()蚕愤,一但有客戶端進(jìn)來(lái),所有進(jìn)程的accept()都會(huì)返回籍凝,但是只有一個(gè)進(jìn)程會(huì)讀到數(shù)據(jù)苹享,就是驚群宫纬。
Nginx 采用accept-mutex來(lái)解決驚群?jiǎn)栴}:當(dāng)一個(gè)請(qǐng)求到達(dá)的時(shí)候,只有競(jìng)爭(zhēng)到鎖的worker進(jìn)程才會(huì)驚醒處理請(qǐng)求,其他進(jìn)程會(huì)繼續(xù)等待椒楣,結(jié)合 timer_solution 配置的最大的超時(shí)時(shí)間繼續(xù)嘗試獲取accept-mutex
從I/O復(fù)用角度談 nginx 和apache 的區(qū)別
I/O 復(fù)用接口有select 和 epoll 兩種模型拧抖,首先介紹一下這兩種模型的執(zhí)行方式:
- select 模型:說(shuō)的通俗一點(diǎn)就是各個(gè)客戶端連接的文件描述符也就是套接字徒仓,都被放到了一個(gè)集合中,調(diào)用select函數(shù)之后會(huì)一直監(jiān)視這些文件描述符中有哪些可讀吭净,如果有可讀的描述符那么我們的工作進(jìn)程就去讀取資源晤斩。PHP 中有內(nèi)置的函數(shù)來(lái)完成 select 系統(tǒng)調(diào)用维苔。select()所維護(hù)的 存儲(chǔ)大量文件描述符的數(shù)據(jù)結(jié)構(gòu) 褐澎,隨著文件描述符數(shù)量的增長(zhǎng)段审,其在用戶態(tài)和內(nèi)核的地址空間的復(fù)制所引發(fā)的開(kāi)銷也會(huì)線性增長(zhǎng)
由于網(wǎng)絡(luò)響應(yīng)時(shí)間的延遲使得大量TCP連接處于非活躍狀態(tài)催式,但調(diào)用select()還是會(huì)對(duì) 所有的socket進(jìn)行一次線性掃描 萌业,會(huì)
- epoll 模型:epoll 是 select 的增強(qiáng)版授段。epoll 文件描述符數(shù)量無(wú)限制漱抓±儆颍基于事件的就緒通知方式 旨巷,select/poll方式,進(jìn)程只有在調(diào)用一定的方法后靶病,內(nèi)核才會(huì)對(duì)所有監(jiān)視的文件描述符進(jìn)行掃描煤辨,而epoll事件通過(guò)epoll_ctl()注冊(cè)一個(gè)文件描述符,一旦某個(gè)文件描述符就緒時(shí),內(nèi)核會(huì)采用類似call back的回調(diào)機(jī)制,迅速激活這個(gè)文件描述符躬它,epoll_wait()便會(huì)得到通知
調(diào)用一次epoll_wait()獲得就緒文件描述符時(shí)祖娘,返回的并不是實(shí)際的描述符失尖,而是一個(gè)代表就緒描述符數(shù)量的值,拿到這些值去epoll指定的一個(gè)數(shù)組中依次取得相應(yīng)數(shù)量的文件描述符即可渐苏,這里使用內(nèi)存映射(mmap)技術(shù)掀潮, 避免了復(fù)制大量文件描述符帶來(lái)的開(kāi)銷。
在select/poll時(shí)代琼富,服務(wù)器進(jìn)程每次都把這100萬(wàn)個(gè)連接告訴操作系統(tǒng)(從用戶態(tài)復(fù)制句柄數(shù)據(jù)結(jié)構(gòu)到內(nèi)核態(tài))仪吧,讓操作系統(tǒng)內(nèi)核去查詢這些套接字上是否有事件發(fā)生,輪詢完后鞠眉,再將句柄數(shù)據(jù)復(fù)制到用戶態(tài)薯鼠,讓服務(wù)器應(yīng)用程序輪詢處理已發(fā)生的網(wǎng)絡(luò)事件,這一過(guò)程資源消耗較大械蹋,因此出皇,select/poll一般只能處理幾千的并發(fā)連接。
epoll的設(shè)計(jì)和實(shí)現(xiàn)與select完全不同哗戈。epoll通過(guò)在Linux內(nèi)核中申請(qǐng)一個(gè)簡(jiǎn)易的文件系統(tǒng)郊艘,把原先的select/poll調(diào)用分成了3個(gè)部分:
調(diào)用epoll_create()建立一個(gè)epoll對(duì)象(在epoll文件系統(tǒng)中為這個(gè)句柄對(duì)象分配資源)
調(diào)用epoll_ctl向epoll對(duì)象中添加這100萬(wàn)個(gè)連接的套接字
調(diào)用epoll_wait收集發(fā)生的事件的連接
只需要在進(jìn)程啟動(dòng)時(shí)建立一個(gè)epoll對(duì)象,然后在需要的時(shí)候向這個(gè)epoll對(duì)象中添加或者刪除連接谱醇。同時(shí)暇仲,epoll_wait的效率也非常高,因?yàn)檎{(diào)用epoll_wait時(shí)副渴,并沒(méi)有一股腦的向操作系統(tǒng)復(fù)制這100萬(wàn)個(gè)連接的句柄數(shù)據(jù)奈附,內(nèi)核也不需要去遍歷全部的連接。
apache 采用的select模型煮剧,nginx采用epoll模型斥滤,nginx 處理請(qǐng)求是異步非阻塞的将鸵,而apache則是阻塞型的,在高并發(fā)下nginx 能保持低資源低消耗高性能佑颇。在Apache+PHP(prefork)模式下顶掉,如果PHP處理慢或者前端壓力很大的情況下,很容易出現(xiàn)Apache進(jìn)程數(shù)飆升挑胸,從而拒絕服務(wù)的現(xiàn)象痒筒。
Nginx 常用功能
Nginx支持FastCGI、SSL茬贵、Virtual Host簿透、URL Rewrite、Gzip等功能解藻。并且支持很多第三方的模塊擴(kuò)展老充。
Nginx作為Http代理、反向代理:
Nginx通過(guò)配置實(shí)現(xiàn)靈活的轉(zhuǎn)發(fā)功能:Nginx可以根據(jù)不同的正則匹配螟左,采取不同的轉(zhuǎn)發(fā)策略啡浊。
Nginx可以對(duì)返回結(jié)果進(jìn)行錯(cuò)誤頁(yè)跳轉(zhuǎn),異常判斷等胶背。
如果被分發(fā)的服務(wù)器存在異常巷嚣,它可以將請(qǐng)求重新轉(zhuǎn)發(fā)給另外一臺(tái)服務(wù)器,然后自動(dòng)去除異常服務(wù)器奄妨。
Nginx作為負(fù)載均衡器:
Nginx提供的負(fù)載均衡策略有2種:內(nèi)置策略和擴(kuò)展策略涂籽。
內(nèi)置策略為輪詢,加權(quán)輪詢砸抛,Ip hash。
擴(kuò)展策略由第三方實(shí)現(xiàn)树枫。
輪詢與加權(quán)輪詢:
- Ip hash算法直焙,對(duì)客戶端請(qǐng)求的ip進(jìn)行hash操作,然后根據(jù)hash結(jié)果將同一個(gè)客戶端ip的請(qǐng)求分發(fā)給同一臺(tái)服務(wù)器進(jìn)行處理砂轻,可以解決session不共享的問(wèn)題奔誓。
Nginx作為Web緩存
可以把靜態(tài)資源放在Nginx服務(wù)器上(比如前端頁(yè)面資源)
Nginx可以對(duì)不同的文件做不同的緩存處理,配置靈活搔涝。
配合著第三方的ngx_cache_purge厨喂,對(duì)指定的URL緩存內(nèi)容可以的進(jìn)行增刪管理。