只知道 Nginx 牛,卻不知道它怎麼支持百萬並發?

2020-12-13 酷扯兒

本文轉載自【微信公眾號:java進階架構師,ID:java_jiagoushi】經微信公眾號授權轉載,如需轉載與原文作者聯繫

今天,再給大家講講Nginx的整體架構,以及進程模型。Nginx是一個免費的,開源的,高性能的HTTP伺服器和反向代理。以其高性能,穩定性,豐富的功能,簡單的配置和低資源消耗而聞名。Nginx是一個Web伺服器,也可以用作負載均衡器和HTTP緩存。

很多高知名度的網站都使用Nginx,比如:Netflix,GitHub,SoundCloud,MaxCDN等。

1.Nginx的整體架構

1.1.主進程

Nginx啟動時,會生成兩種類型的進程,一個是主進程(master),一個(windows版本的目前只有一個)或多個工作進程(worker)。

主進程並不處理網絡請求,主要負責調度工作進程,也就是圖示的3項:加載配置、啟動工作進程、非停升級

因此,Nginx啟動以後,查看作業系統的進程列表,我們就能看到至少有兩個Nginx進程。

1.2.工作進程

伺服器實際處理網絡請求及響應的是工作進程(worker),在類unix系統上,Nginx可以配置多個worker,而每個worker進程都可以同時處理數以千計的網絡請求。

1.3.模塊化設計

Nginx的worker進程,包括核心和功能性模塊,核心模塊負責維持一個運行循環(run-loop),執行網絡請求處理的不同階段的模塊功能。

比如:網絡讀寫、存儲讀寫、內容傳輸、外出過濾,以及將請求發往上遊伺服器等。

而其代碼的模塊化設計,也使得我們可以根據需要對功能模塊進行適當的選擇和修改,編譯成具有特定功能的伺服器。

1.4.事件驅動模型

基於異步及非阻塞的事件驅動模型,可以說是Nginx得以獲得高並發、高性能的關鍵因素,同時也得益於對Linux、Solaris及類BSD等作業系統內核中事件通知及I/O性能增強功能的採用,如kqueue、epoll及eventports。

1.5.代理(proxy)設計

代理設計,可以說是Nginx深入骨髓的設計,無論是對於HTTP,還是對於FastCGI、Memcache、Redis等的網絡請求或響應,本質上都採用了代理機制。所以,Nginx天生就是高性能的代理伺服器。

2.Nginx的模塊化設計

高度模塊化的設計是Nginx的架構基礎。Nginx伺服器被分解為多個模塊,每個模塊就是一個功能模塊,只負責自身的功能,模塊之間嚴格遵循「高內聚,低耦合」的原則。

如下圖所示:

2.1.核心模塊

核心模塊是Nginx伺服器正常運行必不可少的模塊,提供錯誤日誌記錄、配置文件解析、事件驅動機制、進程管理等核心功能。

2.2.標準HTTP模塊

標準HTTP模塊提供HTTP協議解析相關的功能,比如:埠配置、網頁編碼設置、HTTP響應頭設置等等。

2.3.可選HTTP模塊

可選HTTP模塊主要用於擴展標準的HTTP功能,讓Nginx能處理一些特殊的服務,比如:Flash多媒體傳輸、解析GeoIP請求、網絡傳輸壓縮、安全協議SSL支持等。

2.4.郵件服務模塊

郵件服務模塊主要用於支持Nginx的郵件服務,包括對POP3協議、IMAP協議和SMTP協議的支持。

2.5.第三方模塊

第三方模塊是為了擴展Nginx伺服器應用,完成開發者自定義功能,比如:Json支持、Lua支持等。

3.Nginx的請求方式處理

Nginx是一個高性能的Web伺服器,能夠同時處理大量的並發請求。它結合多進程機制和異步機制,異步機制使用的是異步非阻塞方式,接下來就給大家介紹一下Nginx的多線程機制和異步非阻塞機制。

3.1.多進程機制

伺服器每當收到一個客戶端時,就有伺服器主進程(master process)生成一個子進程(worker process)出來和客戶端建立連接進行交互,直到連接斷開,該子進程就結束了。

使用進程的好處是各個進程之間相互獨立,不需要加鎖,減少了使用鎖對性能造成影響,同時降低編程的複雜度,降低開發成本。

其次,採用獨立的進程,可以讓進程互相之間不會影響,如果一個進程發生異常退出時,其它進程正常工作,master進程則很快啟動新的worker進程,確保服務不會中斷,從而將風險降到最低。

缺點是作業系統生成一個子進程需要進行內存複製等操作,在資源和時間上會產生一定的開銷。當有大量請求時,會導致系統性能下降。

3.2.異步非阻塞機制

每個工作進程使用異步非阻塞方式,可以處理多個客戶端請求。

當某個工作進程接收到客戶端的請求以後,調用IO進行處理,如果不能立即得到結果,就去處理其他請求(即為非阻塞),而客戶端在此期間也無需等待響應,可以去處理其他事情(即為異步)

當IO返回時,就會通知此工作進程,該進程得到通知,暫時掛起當前處理的事務去響應客戶端請求。

4.Nginx事件驅動模型

在Nginx的異步非阻塞機制中,工作進程在調用IO後,就去處理其他的請求,當IO調用返回後,會通知該工作進程。

對於這樣的系統調用,主要使用Nginx伺服器的事件驅動模型來實現,如下圖所示:

如上圖所示,Nginx的事件驅動模型由事件收集器、事件發送器和事件處理器三部分基本單元組成。

事件收集器:負責收集worker進程的各種IO請求;

事件發送器:負責將IO事件發送到事件處理器;

事件處理器:負責各種事件的響應工作。

事件發送器將每個請求放入一個待處理事件列表,使用非阻塞I/O方式調用事件處理器來處理該請求。

其處理方式稱為「多路IO復用方法」,常見的包括以下三種:select模型、poll模型、epoll模型。

5.Nginx進程處理模型

Nginx伺服器使用 master/worker 多進程模式,多線程啟動和執行的流程如下:

主程序Masterprocess啟動後,通過一個for循環來接收和處理外部信號

主進程通過fork()函數產生worker子進程,每個子進程執行一個for循環來實現Nginx伺服器對事件的接收和處理

一般推薦worker進程數與CPU內核數一致,這樣一來不存在大量的子進程生成和管理任務,避免了進程之間競爭CPU資源和進程切換的開銷。

而且Nginx為了更好的利用多核特性,提供了CPU親緣性的綁定選項,我們可以將某一個進程綁定在某一個核上,這樣就不會因為進程的切換帶來Cache的失效。

對於每個請求,有且只有一個工作進程對其處理。首先,每個worker進程都是從master進程fork過來。在master進程裡面,先建立好需要listen的socket(listenfd)之後,然後再fork出多個worker進程。

所有worker進程的listenfd會在新連接到來時變得可讀,為保證只有一個進程處理該連接,所有worker進程在註冊listenfd讀事件前搶佔accept_mutex

搶到互斥鎖的那個進程註冊listenfd讀事件,在讀事件裡調用accept接受該連接。

當一個worker進程在accept這個連接之後,就開始讀取請求,解析請求,處理請求,產生數據後,再返回給客戶端,最後才斷開連接,一個完整的請求就是這樣。

我們可以看到,一個請求,完全由worker進程來處理,而且只在一個worker進程中處理。

如下圖所示:

在Nginx伺服器的運行過程中,主進程和工作進程需要進程交互。交互依賴於Socket實現的管道來實現。

5.1.主進程與工作進程交互

這條管道與普通的管道不同,它是由主進程指向工作進程的單向管道,包含主進程向工作進程發出的指令工,作進程ID等。同時主進程與外界通過信號通信;每個子進程具備接收信號,並處理相應的事件的能力。

5.2.工作進程與工作進程交互

這種交互和主進程-工作進程交互基本一致,但是會通過主進程間接完成,工作進程之間是相互隔離的。

所以當工作進程W1需要向工作進程W2發指令時,首先找到W2的進程ID,然後將正確的指令寫入指向W2的通道,W2收到信號採取相應的措施。

相關焦點

  • Nginx在高並發下的性能優化點!有這篇就夠了!
    實際我們填入一個65535,足夠了,這些都算並發值,一個網站的並發達到這麼大的數量,也算一個大站了!reset_timeout_connection :告訴nginx關閉不響應的客戶端連接。這將會釋放那個客戶端所佔有的內存空間。send_timeout :響應客戶端超時時間,這個超時時間僅限於兩個活動之間的時間,如果超過這個時間,客戶端沒有任何活動,nginx關閉連接。
  • 不知道如何做性能測試,那就從這三方面入手
    通過這兩個案例,我們知道,在一些極限的場景下,軟/件和硬體會造成極大的破壞和損失,因此,我們需要進行性能測試,來驗證軟體在高壓力下,高並發下,高負載下的實際工作情況。2.比如:apache、nginx、rabbitmq、storm、zookeeper、dubbo、mysql資料庫等。
  • 支撐百萬高並發內核參數調優
    眾所周知在默認參數情況下Linux對高並發支持並不好,主要受限於單進程最大打開文件數限制、內核TCP參數方面和IO事件分配機制等。下面就從幾方面來調整使Linux系統能夠支持高並發環境。當並發請求過多的時候,就會產生大量的TIME_WAIT狀態的連接,無法及時斷開的話,會佔用大量的埠資源和伺服器資源。這個時候我們可以優化TCP的內核參數,來及時將TIME_WAIT狀態的埠清理掉。下面介紹的方法只對擁有大量TIME_WAIT狀態的連接導致系統資源消耗有效,如果不是這種情況下,效果可能不明顯。
  • 「技術專刊」WebApi部署多伺服器配置Nginx負載均衡
    其特點是佔有內存少,並發能力強,事實上nginx的並發能力在同類型的網頁伺服器中表現較好,中國大陸使用nginx網站用戶有:百度、京東、新浪、網易、騰訊、淘寶等。下面就演示一下配置Nginx的過程1.下載Nginx包:http://nginx.org/en/download.html 注意下載存儲Nginx包的路徑必須為英文;不能帶有中文字符;2.啟動Nginx:直接到下載的Nginx包中雙擊打開「nginx.exe」即可,也可以通過命令啟動
  • 單機伺服器最大並發的TCP連接數到底是多少,你被騙很久!
    本文轉載自【微信公眾號:小碼逆襲,ID:gh_7c5a039380a0】經微信公眾號授權轉載,如需轉載與原文作者聯繫曾幾何時我們還在尋求網絡編程中C10K問題的解決方案,但是現在從硬體和作業系統支持來看單臺伺服器支持上萬並發連接已經沒有多少挑戰性了。
  • Nginx專題之-父子進程的架構(打虎親兄弟worker,上陣父子兵)
    其實單進程結構不適合生成環境,只是用於開發系統調試使用的。在生成環境中我們必須保證足夠系統健壯性,並且能夠利用內核的特性發揮更大的效果。Nginx為什麼是多進程結構呢,最核心的原因是nginx要保證它的高可用性,高可靠性。多線程是共享同一塊內存地址空間的,如果由於某些原因導致某個線程發生錯誤或者地址越界,會導致整個Nginx進程宕掉。多進程就不會出現這樣的情況。第三方模塊不會在master進程添加自己的功能代碼的(Nginx在設計的允許添加自定義的方法,不過很少有人這麼做)。
  • JAVA並發編程:並發問題的根源及主要解決方法
    並發問題的根源在哪首先,我們要知道並發要解決的是什麼問題?並發要解決的是單進程情況下硬體資源無法充分利用的問題。而造成這一問題的主要原因是CPU-內存-磁碟三者之間速度差異實在太大。如果將CPU的速度比作火箭的速度,那麼內存的速度就像火車,而最慘的磁碟,基本上就相當於人雙腿走路。
  • 12生肖牛的來歷:屬牛的朋友們注意了,屬牛也要知道來歷
    12生肖牛的寓意是勤勞質樸,吃苦耐勞,古代牛作為祭祀動物,在人們心中有著重要的地位,大家知道老牛怎麼變成12生肖嗎?看看下面吧!傳說以前牛是玉帝殿前的下級,經常往返於天宮和大地之間。玉帝覺得牛是個粗心大意的傢伙,雖然這個任務不能害怕,但是牛堅持要去。最後玉帝同意了牛的要求,牛王來到人間後,走三步撒了草種。牛拿著草的種子出了天宮,出了南天門的時候,不小心摔倒了,到了人間後,頭腦發昏,誤以為玉帝的目的是一步三種草的種子。於是,許多草的種子被撒在了大地上。
  • 怎麼才能夠知道自己的手機,支不支持北鬥定位呢
    【怎麼才能夠知道自己的手機,支不支持北鬥定位呢】我們先得排除一種大家可能都會下意識的認為,存在所謂的北鬥地圖。實際上,你在所謂的網絡中看到的北鬥地圖是完全不存在的,沒有所謂的北鬥地圖,都是一些應用廠商弄出來給混淆消費者的。
  • 「貔貅」您可能只知道它寓意只進不出,其實它還是神話中的兇獸!
    大家可以看到有貔貅的雕塑修建在古代某位王侯將相的墳墓前,用作闢邪,同時也是守護的意思,在現代人們也可以看到有的城市的大門處有它的雕塑,估計也是因為它在天庭擔任巡視和守護的工作,希望它能維持一個城市的良好風氣和良好秩序。
  • 夜讀|牛不知道自己的力氣有多大
    「又打牛了!」老人說,「牛通人性。你老是打牛,牛就會反抗,就會怨恨。你要把牛當人看待,多和它講話,它聽得懂的。我只要哼一聲,它就曉得是什麼意思。」 兒子不吭聲。終於把泥帶到父親指定的水凼裡。 「上來抽筒煙吧!」老人說。 兒子便吆住牛。
  • 爆笑校園:呆頭農場超級物種「長頸牛」?呆頭:我怎麼以前不知道
    爆笑校園:呆頭農場超級物種「長頸牛」?呆頭:我怎麼以前不知道
  • 常州偶遇最「牛」奧迪,看懂車牌的含義後,才知道車主有多壕!
    導讀:說起奧迪,大家都知道它是德系三大豪華車品牌之一,在全球各地都遍布著它的真愛粉。單論品質的話,奧迪要比寶馬和奔馳稍差一些,而它旗下的車型定位也是相對較低,入門級車型在二十萬左右,頂級的旗艦版車型在百萬左右。
  • 《只狼》火牛與櫻牛手殘打法詳解 火牛與櫻牛手殘怎麼打
    導 讀 作為手殘黨在只狼遊戲中遇到強力怪物沒點攻略那就只能殞命,火牛與櫻牛的打法,下面九遊小編就為你們帶來了
  • 微信好友刪除怎麼恢復?不知道帳號可以這樣恢復!
    微信好友刪除怎麼恢復?不知道好友資料可以這樣恢復!基本上每個人都有很多的微信好友,經常會清理一些沒有打備註的微信好友,一不小心就會誤刪了一些重要的朋友,因此想要恢復被自己誤刪的好友,應該用哪些方法呢?看看下面的恢復辦法吧!就算沒有好友的微信帳號也能輕鬆恢復哦!
  • js頁面觸發chargeRequest事件和Nginx獲取日誌信息
    --- ip地址$msec^A ----訪問時間,時間戳,毫秒$http_host^A ----所訪問的主機名$request_uri ---用戶請求參數,從客戶端捕獲到的用戶行為數據都會封裝到這個欄位裡我們打開伺服器將Nginx配置nginx.conf
  • 和牛?雪花牛肉?傻傻分不清?三分鐘立刻了解
    我們常常能夠在菜單上看到雪花牛肉、肥牛、日本和牛、澳洲和牛等字眼,花了吃普通牛肉幾倍的錢,卻不知道和普通牛肉有什麼區別,今天就來一起見識一下吧。牛肉是我們日常食用的肉類中最具營養價值的肉類,富含豐富的胺基酸,其味道也是許多人難以割捨的美味呢。
  • 印度信奉「牛」不吃牛肉,最後牛都去往何處?不看的話一定不知道
    美國的經濟水平比較高,而且當地養殖牛的農戶是很多的。因此牛肉就成為美國人喜歡吃的一種食物,但是在印度牛卻是一種不能吃的動物。因為當地人信仰的宗教不同,印度人是把牛信奉為「神」的,所以印度人從來不吃牛肉。圖片來源於網絡,如有侵權請告知刪除若是大家有機會到印度那邊去旅遊的話,千萬要記住這個禁忌。而牛肉在美國可就是當地人非常喜歡吃的一種肉類,不管是做成怎樣的美食都是名氣美食。
  • 農村旱地裡長這樣的草,農民只把它當雜草除掉,卻不知道它的用處
    農村旱地裡長這樣的草,農民只把它當雜草除掉,卻不知道它的用處大家好,這裡是鄉野花草集。歡迎大家閱讀小編的文章。相信很多在鄉裡長大的朋友們對狗尾巴草並不陌生。狗尾巴雖然是生長在農村旱地裡的雜草,其實它還有其它的作用。恐怕很多人還不知道狗尾草對於咱們人體也有著很多的好處吧,那麼今天就讓小編來帶大家就帶大家來了解一下關於狗尾巴草的作用!狗尾草它是一種生長在旱地常見的雜草,對於生長環境的要求並沒有挑剔,所以在農村的旱地裡,荒野旁都能看到它的身影。
  • 農村隨處可見的一種植物,知道名字算你牛,知道作用就更牛了
    今日話題;農村一種植物,知道名字算你牛,知道作用就更牛了。在農村有著許許多多的植物生長,特別是在春季,萬物復甦所有的植物都開始發芽,於是有一些比較難見的植物在這春天發芽的時節或許能有幸見上一面。在這些植物當中,你會沉醉於它的樣子,它的名字還有那一片片點綴後的農村美景。