国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

[轉]深入 NGINX: 為性能和擴展所做之設計

caoym / 2440人閱讀

摘要:常規的網絡應用設計都是為每個連接分配一個線程或進程。深入理解進程每個進程都是用配置進行初始化的,并且由主進程提供了一組監聽套接字。套接字上發生事件后,進程開始進行處理監聽套接字上的事件意味著有個客戶端發起了一盤新的象棋游戲。

NGINX在web性能上的表現尤為出眾,這完全得益于其設計方式,許多web和應用服務器都是基于線程或進程這種簡單的架構,NGINX用了一種精妙的事件驅動架構,在現代的硬件上,它可以處理成千上萬的并發連接。

Inside NGINX中的信息圖對高級別的進程架構和NGINX如何在單個進程中處理多個連接進行了深入探討。本文更進一步地闡述了NGINX的所有工作原理。

背景——NGINX進程模型

要更好的理解這個設計,需要熟悉NGINX的運行過程。NGINX有一個主進程(該進程執行一些特權操作,例如讀取配置以及綁定端口)以及若干worker進程和helper進程。

在這個4核服務器上,NGINX主進程創建了4個worker進程以及一對用來管理磁盤內容緩存的緩存helper進程。

架構為什么重要?

任何Unix應用的基礎都是線程或進程。(從Linux操作系統的角度看,線程和進程幾乎是一樣的;最大的區別是內存共享的度。)一個線程或進程是一組自包含的指令,這些指令可由操作系統調度到某個CPU核心上運行。大部分復雜應用并行運行多個線程或進程一般有兩個原因:

可以同時使用多個CPU核心。

線程和進程讓并行操作變得簡單(例如,同時處理多個連接)。

進程和線程會消耗資源。每個進程或線程都會使用內存以及其他操作系統資源,他們都需要切換CPU(稱作上下文切換)。大部分現代的服務器都能同時處理幾百個小的、活動的線程或進程,但是,一旦內存耗盡或是遇到高I/O負載導致大量上下文切換時性能就會急劇下降。

常規的網絡應用設計都是為每個連接分配一個線程或進程。這種架構簡單且容易實現,但是,當應用需要同時處理成千上萬的連接時,擴展性就不好了。

NGINX是怎么運行的?

NGINX用了一個可預測的進程模型,支持眾多硬件:

主進程執行一些特權操作,比如讀取配置以及綁定端口,然后創建少數子進程(下面的三種類型)。

緩存加載進程在啟動時運行,用于將磁盤上的緩存加載到內存中,隨后退出。對這個進程的調度很保守,所以其資源需求比較低。

緩存管理進程會周期性地運行,從磁盤緩存中刪除條目以保證緩存沒有超過配置的大小。

worker進程做了所有的工作!它們處理網絡連接,從磁盤讀取內容或往磁盤中寫入內容,以及與上游服務器通信。

部分場景中推薦的NGINX配置是 —— 每個CPU核心運行一個worker進程 —— 以充分利用硬件資源。在配置中加入worker_processes auto指令即可:

worker_processes auto;

當NGINX服務器活動時,只有worker進程是處于繁忙狀態的。每個worker進程以非阻塞的方式處理多個連接,這減少了上下文切換的次數。

每個worker進程都是單線程的并且是獨立運行的,它們捕獲新的連接然后進行處理。進程之間的共享緩存數據、會話持久數據以及其它共享資源的通信通過共享內存實現。

深入理解NGINX Worker進程

每個worker進程都是用NGINX配置進行初始化的,并且由主進程提供了一組監聽套接字。

NGINX worker進程從等待監聽套接字上的事件開始(accept_mutex和內核套接字切分(kernel socket sharding))。事件由新進來的連接進行初始化。這些連接被分配給一個狀態機 —— HTTP狀態機是最常用的,但NGINX也為流(原始TCP)流量以及一些郵件協議(SMTP,IMAP和POP3)實現了狀態機。

狀態機本質上是一組指令,由它們告訴NGINX如何處理請求。大部分執行與NGINX相同方法的web服務器也用的類似的狀態機 —— 區別在于實現。

狀態機的調度

將狀態機想象成象棋規則。每個HTTP事務就是一盤象棋游戲。棋盤的一側是web服務器 —— 一個可以快速做決定的象棋大師。另一側是遠程客戶端 —— 正在相對較慢的網絡中訪問站點或應用的web瀏覽器。

然而,游戲的規則可能會非常復雜。比如,web服務器也許要與其它方(代理到上游應用)進行交流或是要與認證服務器對話。web服務器中的第三方模塊甚至還可能擴展游戲規則。

阻塞模式的狀態機

前面我們提到,一個線程或進程是一組自包含的指令,這些指令可由操作系統調度到某個CPU核心上運行。大部分web服務器以及web應用使用的是每個連接分配一個進程或每個連接分配一個線程的模式來處理的。每個進程或線程都包含了從開始到結束需要執行的指令。在服務器運行進程期間,大部分時間都是“阻塞的” —— 等待客戶端完成其下一個動作。

web服務器進程在監聽套接字上監聽新的連接(由客戶端初始化的新游戲)。

當新游戲準備好后,就開始游戲,每個動作之后都會阻塞,等待客戶端的響應。

一旦游戲結束,web服務器進程可能還要等等看是否這個客戶端需要發起一輪新的游戲(這相當于keepalive連接)。如果連接被關閉(客戶端離開或超時),web服務器進程返回去監聽新的游戲請求。

關鍵的一點在于每個活動的HTTP連接(每盤象棋游戲)都需要一個專門的進程或線程(一個象棋大師)。這種架構在擴展第三方模塊(“新的規則”)時非常簡單方便。然而,存在一個巨大的失衡問題:相當輕量級的HTTP連接,本由一個文件描述符和少量的內存來表示,卻映射到了一個多帶帶的線程或進程這種非常重量級的操作系統對象。編程是便利了,但卻是個很大的浪費。

NGINX是真大師

也許你已經聽過simultaneous exhibition游戲,一個象棋大師同時與幾十個對手對戰。

這就是NGINX worker進程下“象棋”的方式。每個worker進程(記住 —— 通常是每個CPU核心一個worker進程)都是一個大師,可以同時處理幾百盤(實際上是成千上萬)游戲。

worker進程等待監聽和連接套接字上的事件。

套接字上發生事件后,worker進程開始進行處理:

監聽套接字上的事件意味著有個客戶端發起了一盤新的象棋游戲。worker進程創建出一個新的連接套接字。

連接套接字上的事件意味著客戶端開始有新的動作了。worker進程就迅速響應。

worker進程永遠不會因為網絡擁堵而阻塞來等待“對手”(客戶端)的響應。當處理完一個動作,worker進程立即去處理其他游戲中等待處理的動作,或是迎接新玩家的到來。

為什么這比阻塞的、多進程架構更快?

NGINX的可伸縮性非常好,每個worker進程可以支撐成千上萬個連接。每個新的連接會創建一個文件描述符以及消耗worker進程中少量的額外內存。每個連接的額外開銷極少。NGINX進程可以綁定到CPU。上下文切換是比較罕見的,只有沒有任務要處理時才會發生。

在阻塞的、每個連接一個進程的方式下,每個連接都需要大量的額外資源與開銷,且上下文切換(從一個進程切換到另一個)非常頻繁。

更多細節解釋,看看這篇有關NGINX架構的文章。

通過適當的系統調優,NGINX worker進程可以處理成千上萬的并發HTTP連接,能夠承受流量峰值(新游戲蜂擁而至)還不會錯過一個請求。

配置更新與NGINX升級

NGINX這種使用少數worker進程的進程架構,可以非常高效的進行配置更新甚至是更新NGINX介質本身。

更新NGINX配置是個很簡單、輕量級且可靠的操作。通常只是意味著去運行一下nginx –s reload命令,這個命令會去檢查磁盤上的配置,給主進程發送一個SIGHUP信號。

當主進程收到SIGHUP信號,會做兩件事:

重新加載配置,然后fork出一組新的worker進程。這些新的worker進程會立馬開始接受連接并處理(用的是新的配置)。

發信號讓舊的worker進程優雅退出。舊的worker進程停止接受新的連接。一旦每個當前的HTTP請求完成,worker進程將利索地結束連接(也就是,沒有lingering keeplive)。一旦所有連接都關閉了,worker進程就可以退出了。

這個配置加載進程會造成CPU和內存使用上的一個小峰值,但相比活動的連接帶來的資源負載,這是極其微小的。可以每秒重新加載配置多次(有許多NGINX用戶的確是這么干的)。多代NGINX worker進程都在等待連接關閉極少會造成問題,但即便有問題也會很快解決。

NGINX介質升級過程達到了高可用性的標準 —— 可以直接對線上運行的NGINX升級,而不會丟失任何連接,也不會有停機時間與服務中斷。

介質升級過程與重新加載配置的過程類似。一個新的NGINX主進程會與舊的主進程并行運行,它們共享監聽套接字。兩個進程都是活動的,并且各自對應的worker進程都還在處理請求。隨后可以發信號讓舊的主進程及其worker進程優雅退出。

整個過程在Controlling NGINX中有更詳細的描述。

總結

這篇深入NGINX信息圖從高層次概述了NGINX的功能,但是在這個簡單解釋的背后,是十多年的創新與優化,才使NGINX在保證安全和可靠性的同時,在眾多硬件上都能發揮出最佳性能。

本文來源地址:[譯]深入 NGINX: 為性能和擴展所做之設計

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/39173.html

相關文章

  • PHP程序員學習路線

    摘要:第一階段基礎階段基礎程序員重點把搞熟練核心是安裝配置基本操作目標能夠完成基本的系統安裝,簡單配置維護能夠做基本的簡單系統的開發能夠在中型系統中支持某個功能模塊的開發。本項不做重點學習,除非對前端有興趣。 第一階段:基礎階段(基礎PHP程序員) 重點:把LNMP搞熟練(核心是安裝配置基本操作) 目標:能夠完成基本的LNMP系統安裝,簡單配置維護;能夠做基本的簡單系統的PHP開發;能夠在P...

    genedna 評論0 收藏0
  • 學習JVM必看書籍

    學習JVM的相關資料 《深入理解Java虛擬機——JVM高級特性與最佳實踐(第2版)》 showImg(https://segmentfault.com/img/bVbsqF5?w=200&h=200); 基于最新JDK1.7,圍繞內存管理、執行子系統、程序編譯與優化、高效并發等核心主題對JVM進行全面而深入的分析,深刻揭示JVM的工作原理。以實踐為導向,通過大量與實際生產環境相結合的案例展示了解...

    shaonbean 評論0 收藏0
  • 深入 Nginx 之架構篇

    摘要:請求的多階段異步處理多階段異步處理請求與事件驅動架構是密切相關的,也就是說,請求的多階段異步處理只能基于事件驅動架構實現。 前言 最近在讀 Nginx 相關的書籍,做一下讀書筆記。 Nginx 作為業界知名的高性能服務器,被廣泛的應用。它的高性能正是由于其優秀的架構設計,其架構主要包括這幾點:模塊化設計、事件驅動架構、請求的多階段異步處理、管理進程與多工作進程設計、內存池的設計,以下內...

    linkin 評論0 收藏0
  • 深入 Nginx 之架構篇

    摘要:請求的多階段異步處理多階段異步處理請求與事件驅動架構是密切相關的,也就是說,請求的多階段異步處理只能基于事件驅動架構實現。 前言 最近在讀 Nginx 相關的書籍,做一下讀書筆記。 Nginx 作為業界知名的高性能服務器,被廣泛的應用。它的高性能正是由于其優秀的架構設計,其架構主要包括這幾點:模塊化設計、事件驅動架構、請求的多階段異步處理、管理進程與多工作進程設計、內存池的設計,以下內...

    zhangrxiang 評論0 收藏0
  • 一個 16年畢業生所經歷的 PHP 面試

    摘要:正確做法是給加索引,還有聯合索引,并不能避免全表掃描。 前言:有收獲的話請加顆小星星,沒有收獲的話可以 反對 沒有幫助 舉報三連 有心的同學應該會看到我這個noteBook下面的其它知識,希望對你們有些許幫助。 本文地址 時間點:2017-11 一個16年畢業生所經歷的php面試 一、什么是面試 二、面試準備 1. 問:什么時候開始準備? 2. 問:怎么準備? 三、面試...

    dabai 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<