首頁  >  文章  >  後端開發  >  Nginx 是如何為效能和規模設計的?

Nginx 是如何為效能和規模設計的?

WBOY
WBOY原創
2016-08-08 09:18:581674瀏覽
NGINX 在網路應用中表現超群,在於其獨特的設計。許多網路或應用程式伺服器大都是基於執行緒或進程的簡單框架,NGINX突出的地方就在於其成熟的事件驅動框架,它能應對現代硬體上成千上萬的並發連接。
NGINX 內部資訊圖表從進程框架的頂層開始,向下逐步揭示NGINX如何處理單一進程中的多個連接,並進一步探討其工作機制。
場景設定 — NGINX進程模型
NGINX擁有一個主線程,用來處理設定檔的讀取、連接埠的綁定等特權操作,以及一組工作進程、輔助進程。

# service nginx restart* Restarting nginx

# ps -ef --forest | grep nginx

root 32475 1 0 13:36 ? 00:00:00 nginx: master process /usr/sbin /nginx

-c /etc/nginx/nginx.conf

-c /etc/nginx/nginx.conf

nginx 32476 32475 0 13:36 ? 00:00:00 _ nginx: worker process

? _ nginx: worker process

nginx 32479 32475 0 13:36 ? 00:00:00 _ nginx: worker process

nginx 32480 32475 0 133:00:00:00:00 32475 0 13:030

nginx 32481 32475 0 13:36 ? 00:00:00 _ nginx: cache manager process

nginx 32482 32475 0 13:36 ? 00:00:00 _ nginx: cache loader process

執行緒創建了四個工作進程和一組快取輔助進程(cache helper processes),後者用來管理硬碟快取。


為什麼框架如此重要?
任何Unix應用的基礎是執行緒或進程-對於Linux作業系統,執行緒和進程幾乎相同;最大的區別在於執行緒間是記憶體共享的。一個執行緒或進程是一套指令集(self-contained set of instructions ),作業系統調度這些指令在單一CPU核心上運行。許多複雜應用程式並行地運行在多個執行緒或進程,原因有二:
  • 應用可以同時使用電腦的多個CPU核

  • 執行緒和進程易於並行操作,例如同時處理多個連線


  • 其它作業系統資源的佔用、核心切換(wapped on and off the cores)(本操作叫做一次上下文切換(context switch))。現今的伺服器需要同時處理成千個小的、活躍執行緒或進程,一旦記憶體耗盡、或過高的讀寫負載,這些都會導致大規模的上下文切換,效能會嚴重退化。
    通常的設計思路是,網路應用為每個連接分派一個執行緒或進程。這類框架簡單易於實現,不過在同時應對成千上萬個連接時難以擴展。
    NGINX是如何運作的呢?
    NGINX利用一個預測進程模型調度可用的硬體資源:
    主進程處理配置文件、端口綁定等特權操作,以及接下來創建一子主進程(三種類型的進程)
  • 啟動時快取載入器進程載入硬碟中快取到記憶體中,接著退出。對它的調度是保守的,所以資源開銷較低
  • 快取管理進程定時運行,清理來自硬碟快取的實體到指定的大小
  • 工作進程負責所有的工作,處理網路連接、硬碟讀取寫入操作、以及上游伺服器通訊

  • NGINX建議的配置是,一個工作進程對應一個CPU內核,確保硬體資源的有效利用,在設定檔中設定worker_processes auto:_ auto;
    一旦NGINX服務起來,僅有工作進程在忙,每個工作進程採用非阻塞地方式處理多個連接,降低上下文切換的次數。

    每個工作進程都是單執行緒且獨立運行,負責取得新連線並進行處理。進程之間透過共享記憶體進行通信,諸如快取數據,會話持續化數據(ession persistence data),以及其他共享資源。 NGINX1.7.11及以後的版本,有一個可選的執行緒池,工作進程將阻塞操作丟給它們。更多細節,請參考《Nginx 引入線程池,提升 9 倍效能》。對於NGINX Plus用戶,這些新功能會在今年的發布版7中出現。
    NGINX內部工作流程
    IN
    工作進程起始於socket監聽事件(accept_mutex 和kernel socket sharding),事件由新的連線進行初始化,接著這些連線被派發給某個狀態機—HTTP狀態機是其中最常用的一種,不過NGINX也實作了基於流的狀態機、基於通訊協定的狀態機(SMTP, IMAP, and POP3)。

    狀態機是一組重要的指令集,它會告訴NGINX怎麼處理每個請求。許多網路伺服器擁有NGINX的狀態機一樣的功能—差別就在於它們的實作不同。

    調度狀態機狀態機就像下棋,單一HTTP事務如同一盤棋。棋盤的一端是網頁伺服器—就像大師級棋手非常快速地做出決定,另一端為遠端客戶端—網頁瀏覽器透過相對較慢的網路存取某個網站或應用程式。
    不過遊戲規則可能非常複雜,例如網路服務可能需要和第三方、或者某個認證伺服器通信,甚至伺服器中的第三方模組來擴展遊戲規則。
    阻塞狀態機
    回到前面的描述,進程或執行緒作為一套指令集,作業系統調度其運行在某個CPU核心上。大多數網頁伺服器和網路應用程式按照一個行程處理一個連接,或一個執行緒處理一個連接的模型來玩象棋遊戲;每個包含指令的進程或執行緒參與遊戲的整個過程。在這段期間,運行在伺服器上進程大多數時間都被阻塞掉了,也就是等待某個客戶端去完成下一步棋。

  • 網路伺服器進程監聽socket上的新連接,此遊戲新連接由客戶端發起。

  • 一旦獲得新遊戲,進入遊戲環節,每一次移動都需等待客戶端回應,進程就被阻塞了。

  • 一旦遊戲結束,網頁伺服器進程就會查看客戶端是否想再來一局(對應某個存活的連線)。一旦連線關閉(客戶端離開或逾時),網頁伺服器程序就會返回監聽新的遊戲。


  • 記住每一個活躍的HTTP連接即每一局象棋遊戲,需要像棋大師一般的特定進程或者線程參與其中。這個架構簡單容易擴展第三方模型即新的規則。然而,這裡存在一個極不平衡的邏輯,對於相關輕量級的HTTP連接,由單個文件描述符和少量的內存表示,此連接會映射到某個線程或進程上,而線程或者進程是一個重量級的作業系統物件。儘管編程時很方便,但浪費卻是巨大的。
    NGINX是真正的大師
    或許你聽說過同時展示遊戲,一個象棋大師同時對陣十二個棋手。

    NGINX工作進程也是這麼玩」象棋」的,每個工作進程-一個CPU核心上的工作者-即是一個可以同時應對成千上萬遊戲的大師。

  • 工作進程從已連接並開始監聽的套接字(socket)那裡獲取事件;

  • 進程
    • socket上的某個監聽事件即客戶端開啟一個新的象棋遊戲,而工作進程創建一個新的socket連線。
    • socket連線上的某個事件即客戶端走了一步棋,工作執行緒做出了適當地回應。

    工作進程從來不會阻塞在網路傳輸上等待它的對手(客戶端)回覆回應。每走完一步棋後,工作進程會迅速處理其它等待的象棋遊戲,或歡迎新的遊戲玩家進入。
    為何比阻塞、多進程框架快呢?
    NGINX良好的擴展性在於其支援一個工作執行緒處理成千上萬個連線。每個新連接創建文件描述符,僅消耗工作進程很少一部分額外內存,額外的開銷很小。進程能夠一直綁定CPU(pinned to CPUs),這樣上下文切換相對沒有那麼頻繁,只有沒工作時才會發生。 譯者註:cpu綁定是指綁定一個或多個進程到一個或多個處理器上.
    使用阻塞方式,即一個連接對應一個進程,每個連接需要大量的額外資源以及開銷,上下文切換非常頻繁。
    (更多細節,請參閱Andrew Alexeev關於NGINX架構的文章。作者是NGINX聯合創始人、公司開發部副總裁。)
    只要恰當的系統調優,NGINX進程可以處理成千上萬個並發HTTP連接,毫無差錯地應對網路高峰,即同時可以玩更多的象棋遊戲。 更新設定檔升級NGINX
    進程框架擁有少量工作進程,有利設定檔甚至二進位檔案更新。

    更新NGINX配置是一個簡單、輕量級的可靠操作。即只要執行nginx -s reload指令,就會檢查磁碟上的設定文件,並傳送一個SIGHUB訊號給主程序。
    一旦主進程接受到一個SIGHUB,它會做兩件事:
  • 重載配置文件、創建一組新的工作進程,新創建的工作進程立即接受連接網路通訊( 採用新的配置環境)。

  • 通知舊的工作進程優雅地推出,這些工作進程停止接受新連線。一旦目前處理的HTTP請求結束,工作進程會關閉連線。一旦所有連線關閉,工作進程就會退出。


  • 重載進程會造成一個小的CPU和記憶體高峰,不過從活躍連線載入的資源相比,開銷微乎其微。每一秒可以多次重載設定檔。產生諸多等待連線關閉的NGINX工作進程一般很少出問題,不過就算是有問題也可以迅速解決。
    NGINX二進文件升級獲得極佳的高可用性-你可以在線升級文件,而且不會丟失任何連接、服務也不會停機或中斷。 譯者註: on the fly 程式在運作時,工作就可以完成。

    二進位檔案升級進程方式類似優雅的設定檔重載;新的NGINX主進程和原有的主進程並行,分享監聽socket。兩個進程都處於活躍狀態,處理它們各自的網路通訊。你可以通知原有的主流程以及它的工作流程優雅地退出。
    進程詳細描述參見NGINX控制
    最後結語IN
    最後結語IN
    最後結語
    IN
  • 最後結語

  • 不斷創新優化,得益於此NGINX被廣泛應用於各種硬體平台,並且取得了最優異的效能表現。即便是在現代,網路應用需要對安全和可靠性作出維護,NGINX也表現不凡。
  • 倘若你想了解更多關於NGINX優化的知識,以下是一些很不錯的資料:

  • NGININX安裝、效能調優
  • 《Nginx 引入線程池,提升9 倍效能》

    NGINX——開源應用框架

    NGINX socket拆分(Socket Sharding)發布版1.9.1🎜NGINX socket分割(Socket Sharding)發布版1.9.1🎜 🎜 以上就介紹了Nginx 是如何為性能和規模做設計的? ,包括了方面的內容,希望對PHP教程有興趣的朋友有所幫助。 🎜 🎜 🎜
    陳述:
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn