最近在看阿里陶輝前輩寫的」深入理解nginx」中的nginx的事件模組。之所以想看這塊內容,是因為nginx可以處理龐大的並發連接,想看看支持其背後的事件驅動是如何構建的
這篇博文我也不想貼代碼什麼的整一堆東西來講述nginx事件驅動,一來我未必理解的那麼透徹,而來這樣反而更不易閱讀者快速的掌握知識,所以我會簡單的將幾個我認為可能會對我之後的服務器程序開發中有所幫助的幾個知識點
簡單論述nginx的epoll模型
本文只以epoll為例
nginx以epoll為事件驅動的基礎,epoll共檢測4類事件,分別如下
<code>.处理新连接事件 .处理定时事件 .处理普通读写事件 .处理从磁盘读事件 </code>
(1)首先來談第一個處理新連接事件,我們在平時的伺服器設計時,由於連接事件比較敏感(對快速響應要求比較高),所以我會單開一個線程(進程)來專門處理連接,獲取連接後然後在分發給各個I/O復用線程,然而nginx的處理連接事件和處理其他事件都是在同一個I/O復用下,那麼它是如何保證連接事件對響應的要求的呢? niginx是透過將獲取的事件先不呼叫其回調,而是把他們先放入兩個post隊列,這兩個隊列分別為
<code>.ngx_posted_accept_events .ngx_posted_events </code>
第一個隊列用來保存連接事件,而第二個隊列用來保存普通讀寫事件,之後在執行時我們可以先保證ngx_posted_accept_events中的事件先處理,就可以確保連接對響應速度的敏感度
(2)如何防止串話
串話問題可以說是伺服器程式中都需要處理的問題。串話問題是指剛剛關閉了一個套接字,又來了一個新連接,而新連接剛好系統給分配的就是剛關閉的那個套接字,那麼如果方才哪個套接字還有事件未處理完成,接下來它給對應的套接字發送資料很有可能就會發到新建立的用戶那。那麼nginx如何來解決這個問題呢?很簡單,nginx在每次獲得新連接後都會將連接中的一個標誌為置反,這樣本個連接和上個連接的instance就會不同,而每個事件都包含了連接,所以每次處理事件時只需要比較事件中的instance是否相同就OK了
(3)如何處理」驚群問題」
所謂驚群問題就是說多個進程在同時監聽同一個端口,當有連接到來時,系統會把多個進程都喚醒,但是當然任然只有一個進程能處理到新連接,所以本來其他進程是不需要被喚醒的,但是被喚醒了,這就是註明的驚群問題。 nginx解決它的方法也很簡單,只要保證同一時間點只有一個進程在監聽埠就可避免驚群問題了。但是問題的關鍵是如何保證同一時間點只有一個進程來監聽連接埠。 nginx採用了嘗試加鎖,根據加鎖的返回值確定本進程是否要接下來處理新連接事件,從而解決了”驚群問題”
(4)如何解決負載平衡
在我之前寫的一個小網路庫中,我所採用的負載平衡很簡單,就是主線程用來接受新連接,然後輪流把新連接分發給各個子線程,而nginx解決個進程間的負載平衡問題並沒有均衡分配,而是當每個進程處理的額連接數超過了規定其處理的最大連接數的7/8時,就會本次不處理連接,而是將其處理的連接數-1,這樣相當於就把機會讓給了其他線程,從而實現了負載均衡了
總結
關於nginx驅動模組就先寫這麼點吧,隨後在看的時候在不上,寫本片博客只是用來督促自己學習的
').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i ').text(i)); }; $numbering.fadeIn(1700); }); });以上就介紹了走進nginx事件驅動模型,包括了方面的內容,希望對PHP教程有興趣的朋友有所幫助。