深度學習Nginx第四章:Nginx與網絡事件以及驅動模型

  Nginx是一個事件驅動的,主要事件是指網絡事件,Nginx每個網絡連接自然對應兩個網絡事件,一個讀事件一個寫事件。

什麼是網絡事件:

應用層發送get請求,傳輸層主要做一個事情,打開一個端口,把自己端口和nginx端口記錄下來,傳輸層把我們主機ip和目標主機公網ip記錄下來,到達鏈路層通過以太網到我們加的路由器,路由器主要記錄我們所在運營商的ip,通過廣域網跳轉到服務器b的路由器中,通過鏈路層和網絡層以及傳輸層,通過傳輸層我們就知道給我們打開80或者443端口進程也就是nginx,nginx在他們http狀態處理機裏面處理這個請求。TCP層主要做進程與進程間通信的事情,IP層主要解決機器與機器間怎麼找到的問題

報文:

TCP協議與非阻塞接口:

讀事件:Accept:建立連接  、Read:讀消息

寫事件:Write寫消息

其中在事件收集、分發器處理消費者,事件是一個生成者到nginx,不同時間段調用相對於消費者包括openrestry、lua同步代碼

 

Nginx事件循環:

剛剛啓動的時候在wait for events這裏,打開80/443端口,等待新的事件進來,新的客戶端連接事件,這樣的事件對於我們epoll裏面的epoll wait這個方法,當操作系統處理完握手流程完後,就會通知我們epoll wait阻塞方法,然後喚醒我們nginx  work進程,這裏的kernel就是操作系統內核,然後把事件放在事件隊列中,然後右圖處理事件的循環,如果發現新的事件,比如發現一個鏈接新建立了。可能要添加一個操作時間,如果事件內瀏覽器沒有發送請求則關掉鏈接,然後處理完後把響應寫事件在操作系統寫緩存,然後發給瀏覽器中,如果處理完後又到wait for events。 如果使用第三方模塊導致cpu複雜運算,導致處理時間特別長,導致後續隊列大量事件得不到處理,導致惡性循環,然後時間到了,nginx大量處理在連接和不正常斷開,所以nginx不能容忍這個事情,很多第三方都不會一次使用cpu大量計算,而是分段使用

 

epoll的優劣:nginx的事件分發機制,epoll運行nginx事件驅動框架,在那個循環流程中,nginx怎麼樣能夠從操作系統的kernel中獲取等待處理的事件,nginx主要使用epoll這種網絡收集器模型,epoll對於句柄數增加幾乎是無關的,比較適合做大併發連接處理

   在處理事件的時候,雖然可能有一百萬個併發連接,但是活躍的連接可能就這幾百個,select、poll的實現是有問題的,每次取事件的時候都需要把這個一百萬個連接扔給操作系統,讓它一個個判斷那些連接上面有事件進來,epoll就利用這個每次活躍連接佔比非常的特點。每次取活躍連接的時候都會遍歷一個鏈表,這個鏈表裏面只有活躍的鏈接,這樣效率很高,讀取一個少一個(從內核態讀取到用戶態),當操作系統接收到網卡中的一個報文的時候,這個鏈表增加一個新的元素,獲取句柄的時候主需要遍歷這個鏈表。當我們Nginx收到80端口建立連接的請求後,添加一個讀事件,用來讀取http消息,這個時候可能再添加一個新的事件,寫事件,放在紅黑樹中,這個二叉平衡樹可以保證我們的時間複雜度是Logn,當我們不需要處理讀事件或者寫事件的時候我只需要移除這個事件,同樣是Logn的事件複雜度

Nginx的請求切換:

 相比較傳統的服務,比如apache,他們處理的時候是每一個進程處理一個請求,比如p1處理request1的時候,目前網絡事件不滿足的情況下就會切換到p2,可能很快不滿足,比如寫一個響應發現寫緩衝區也已經滿了,也就是網絡中比較擁塞了,滑動窗口沒有向前滑動以至於調用read方法無法寫入這個字節,這個時候阻塞類寫方法一定會導致我們進程間又發生了一次切換,切換到p3,這個時候p3有滿足狀態,接下來執行,這個時候能p3用完了他的時間片又被切換到p1,如此往復,每做一次切換在cpu的頻率下大概是5微妙,但是併發連接和併發線程數增加的時候,這不是一個線性增加,是一個指數增加,會消耗我們很多的計算能力,傳統的是在調用系統的進程調用方法來實現併發連接,而操作系統這種系統調用適用於數百上千的這種進程切換,再多上幾萬幾十萬就無法接受了

  nginx在請求的時候不滿足的時候,用戶態直接切換到綠色請求,這樣就沒有進程間切換的成本,除非是nginx的worker時間片已經使用到了,時間片長度一般是5毫秒-800毫秒,所以可以在配置上把worker的優先級加到最高,比如-19這樣的話操作系統給我們分配的時間片比較大的,這樣才能保證我們nginx在用戶態比較好的完成切換

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章