日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Nginx >内容正文

Nginx

Nginx 架构原理

發(fā)布時(shí)間:2023/12/10 Nginx 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Nginx 架构原理 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Nginx 架構(gòu)

1簡介

Nginx 專注于高性能、高并發(fā)、低內(nèi)存使用率。
功能:load balance,web server,caching,訪問和帶寬控制等等。

2高并發(fā)性為什么這么重要?

系統(tǒng)的并發(fā)情形在過去就一直存在,同時(shí)系統(tǒng)也會具有并發(fā)性,實(shí)現(xiàn)系統(tǒng)的并發(fā)性這個(gè)不難。
現(xiàn)在系統(tǒng)的并發(fā)量不斷變大,那么實(shí)現(xiàn)系統(tǒng)的高并性也越發(fā)重要。

2.1高并發(fā)

2.1.1歷史

過去系統(tǒng)并發(fā)訪問不高,影響因素:Slow clients-users,通信設(shè)備等。

  • Slow clients-users

使用adsl通信,網(wǎng)速慢,下載速度慢;

  • 通信設(shè)備

移動設(shè)備少

2.1.2原因

  • Internet的廣泛普及
  • internet用戶量大
  • 網(wǎng)絡(luò)通信方便快速
  • 移動通信設(shè)備廣泛普及
  • 現(xiàn)代瀏覽器的行為

Another important factor contributing to increased concurrency is the changed behavior of modern browsers, which open four to six simultaneous connections to a website to improve page load speed.
以前加載一個(gè)網(wǎng)頁,只向后端服務(wù)發(fā)送一次數(shù)據(jù)請求;如今為了加快網(wǎng)頁數(shù)據(jù)加載速度,會同時(shí)向后端服務(wù)發(fā)送多次請求;不過這樣會增加后端服務(wù)的并發(fā)量。

  • 長連接

減少了client 與server 的通信latency,but 增加了side of server workload。

2.1.3高并發(fā)的處理方案

1.a website should be based on a number of very efficient building blocks.(高效的構(gòu)建模塊)

2.連接和請求限流。

3.hardware (CPU, memory, disks), network capacity, application and data storage architectures are important for web server software that client connections are accepted and processed.(硬件:資源、軟件:應(yīng)用和數(shù)據(jù)存儲的架構(gòu))

4.數(shù)據(jù)結(jié)構(gòu)、算法

5.the web server should be able to scale nonlinearly with the growing number of simultaneous connections and requests per second(隨著每秒并發(fā)連接和請求數(shù)的增加,web server 應(yīng)該可以非線性伸縮)。
獨(dú)立的服務(wù)器,單節(jié)點(diǎn)資源總是有限的,避免應(yīng)用不受基礎(chǔ)資源,比如硬件資源的影響,我們的應(yīng)用應(yīng)該是可以伸縮的。
如何實(shí)現(xiàn)web server的可伸縮性?通過load balancer可以實(shí)現(xiàn)。
Load balancer自己如何實(shí)現(xiàn)高性能、高效地處理高并發(fā)?大致可以從上面說到的高并發(fā)處理方案中考慮。
同理當(dāng)load balancer達(dá)到高并發(fā)處理瓶頸時(shí),又如何實(shí)現(xiàn)load balancer的可伸縮性呢?一樣需要尋找更強(qiáng)高并發(fā)處理能力的load balancer對它高并發(fā)分流。備注:可能有些load balancer不需要再依賴第三方工具,它本身就有可伸縮性能力。

Nginx基于事件驅(qū)動,不會為每一個(gè)請求而創(chuàng)建大量的進(jìn)程或者線程。當(dāng)負(fù)載增加時(shí),內(nèi)存和cpu的使用率是可控的。

在具備標(biāo)準(zhǔn)硬件的服務(wù)器上,nginx目前可以處理成千上萬的并發(fā)連接。

Handling high concurrency with high performance and efficiency has always been the key benefit of deploying nginx(開發(fā)Nginx的主要目的是:高性能、高效地處理高并發(fā))。

nginx非常適合這樣做,因?yàn)樗峁┝艘恍┲饕墓δ?#xff1a;高并發(fā)分流,延遲處理, SSL (secure sockets layer),靜態(tài)內(nèi)容,壓縮和緩存,連接和請求限流,甚至 HTTP media streaming (長連接中的數(shù)據(jù)流:from the application layer to a much more efficient edge web server layer)。還可以直接與memcahced/redis或者別的nosql解決方案集成,當(dāng)服務(wù)大量的并發(fā)用戶時(shí),可以增加性能。

3架構(gòu)

傳統(tǒng)的基于進(jìn)程or線程的并發(fā)處理模型包括通過一個(gè)獨(dú)立單獨(dú)的進(jìn)程or線程來處理每個(gè)連接,以及阻塞網(wǎng)絡(luò)or IO操作。這種架構(gòu)對于內(nèi)存和cpu的消耗是非常低效的。

生成一個(gè)進(jìn)程或者線程需要準(zhǔn)備一個(gè)新的執(zhí)行環(huán)境,包括:heap 和stack 內(nèi)存的分配;創(chuàng)建新的執(zhí)行上下文。這些操作會花費(fèi)額外的cpu時(shí)間,而且過多的線程,會出現(xiàn)線程上下文頻繁地切換,最終導(dǎo)致性能低。需要有一個(gè)權(quán)衡在“提供一組豐富的通用應(yīng)用特征”和“優(yōu)化服務(wù)器資源利用率”之間。

Nginx的架構(gòu)有更好的性能,它充分有效地利用服務(wù)器資源,受到各種操作系統(tǒng)基于事件的高級機(jī)制的啟發(fā)。一個(gè)模塊化的、事件驅(qū)動的、異步的、單線程的、非阻塞的架構(gòu)。使用多路復(fù)用和事件通知,把一些特定的任務(wù)放到單獨(dú)的進(jìn)程去處理。連接處理是被執(zhí)行在一些有限數(shù)量的worker(是一個(gè)單線程的進(jìn)程)進(jìn)程中一個(gè)高效的run-loop中。每一個(gè)worker每秒可以處理成千上萬個(gè)并發(fā)連接和請求數(shù)。

3.1代碼架構(gòu)

worker code 包含:core 模塊、功能模塊。

3.1.1Core 模塊

負(fù)責(zé)維護(hù)一個(gè)緊密的run-loop,并且在處理請求的每個(gè)階段,選擇執(zhí)行相應(yīng)的模塊(一般指功能模塊)代碼。

3.1.2功能模塊

由表示層和應(yīng)用層功能構(gòu)成。

  • 從網(wǎng)絡(luò)和存儲系統(tǒng)中讀寫數(shù)據(jù);
  • 傳輸數(shù)據(jù)內(nèi)容;
  • 各種出站過濾器(outbound filter);
  • 代理請求(傳送請求到上游服務(wù));
  • 應(yīng)用服務(wù)器端包含的操作;

Nginx 的模塊化架構(gòu)使開發(fā)人員擴(kuò)展功能時(shí),不用去修改core.
nginx包含的模塊有:core module, event modules, phase handlers, protocols, variable handlers, filters, upstreams and load balancers.

當(dāng)處理與接收、處理、和管理網(wǎng)絡(luò)連接和內(nèi)容檢索相關(guān)的各種動作時(shí),nginx使用事件通知機(jī)制和linux、solaris、和基于bsd操作系統(tǒng)的磁盤IO性能加強(qiáng)像kqueue、epoll和event ports。為了能夠及時(shí)地獲取到異步反饋的情況包括:
入站和出站流量;
磁盤操作;
讀取socket和寫socket;
超時(shí)等。

3.2Worker model

Nginx 不會為每個(gè)連接創(chuàng)建一個(gè)進(jìn)程或者線程,通過worker從一個(gè)被共享的“l(fā)isten”socket 接受新的請求,執(zhí)行一個(gè)高效的run-loop 去處理成千上萬的連接。Nginx服務(wù)器會存在多個(gè)worker,接收請求時(shí),請求如何分配到哪個(gè)worker,對此,nginx并沒有指定的仲裁和連接分配,這是由操作系統(tǒng)的內(nèi)核(kernel)機(jī)制決定的。啟動后,會創(chuàng)建一組listen sockets。當(dāng)處理http請求和響應(yīng)時(shí),workers 會從sockets那accept和read,寫socket.

3.2.1Run-loop

Run-loop是worker代碼中最復(fù)雜的部分,包含了內(nèi)部調(diào)用和異步任務(wù)處理。
異步操作是通過模塊化、事件通知、回調(diào)函數(shù)和計(jì)時(shí)器來實(shí)現(xiàn)的。
它的主要原則是盡可能的非阻塞。Nginx唯一會被阻塞的情形是:一個(gè)worker 進(jìn)程沒有足夠的磁盤存儲器性能。

3.2.2內(nèi)存使用小而有效

由于nginx不會為每個(gè)連接生成一個(gè)進(jìn)程或者線程,所以在大多數(shù)情況下,內(nèi)存的使用率是非常小且極其有效的。

在極端的工作負(fù)載下,nginx都可以達(dá)到低cpu使用率,理由如下:
Combined with the careful use of syscalls and an accurate implementation of supporting interfaces like pool and slab memory allocators。

3.2.3節(jié)省cpu周期

因?yàn)闆]有持續(xù)地創(chuàng)建和銷毀進(jìn)程或者線程。

3.2.4Nginx 的工作內(nèi)容

  • 檢查網(wǎng)絡(luò)和存儲器的狀態(tài)
  • 初始化新的連接
  • 把新連接增加到run-loop中
  • Run-loop異步處理連接直到完成,否則連接是不會被回收和從run-loop中移除的

3.2.5伸縮性:多worker進(jìn)程

Nginx 通過生成多個(gè)worker進(jìn)程來處理連接,可以跨多個(gè)cpu核心很好地實(shí)現(xiàn)擴(kuò)展。通常,每個(gè)核心一個(gè)獨(dú)立的worker可以充分利用cpu的多核架構(gòu),也可以防止thread thrashing(過度切換) and lock-ups(死鎖),也不能完全避免死鎖。沒有資源不足,資源控制機(jī)制在單線程worker中是獨(dú)立的;這種模式還可以跨物理存儲設(shè)備進(jìn)行更多的可伸縮性,更多的磁盤利用率,防止磁盤IO阻塞。在通過跨多個(gè)worker共享的工作負(fù)載情況下,服務(wù)器資源被更有效地利用。

3.2.6Worker 數(shù)量調(diào)整

對于某些磁盤使用和CPU負(fù)載模式,應(yīng)該調(diào)整nginx worker的數(shù)量。The rules are somewhat basic here, and system administrators should try a couple of configurations for their workloads.通常建議如下:

  • 如果ngingx 工作負(fù)載是cpu密集型的,比如:處理大量的tcp/ip連接,處理ssl,或者壓縮;那么worker的數(shù)量應(yīng)該和cpu
    核數(shù)一樣。
  • 如果工作負(fù)載是磁盤IO密集型的,比如:從存儲器讀取不同的內(nèi)容集,或者代理;那么worker的數(shù)量是cpu核數(shù)的1.5-2倍。
  • 有些工程師根據(jù)單個(gè)存儲單元的個(gè)數(shù)來選擇workder的數(shù)量,但是這種方式的效率要依賴磁盤存儲器的配置和類型。

3.2.7Nginx開發(fā)中的問題

  • 如何防止磁盤IO上的大量阻塞

對于nginx 開發(fā)者而言,一個(gè)重大的問題需要解決:如何防止磁盤IO上的大量阻塞。

如果沒有足夠的存儲器性能服務(wù)磁盤操作(由worker生成),那么worker會阻塞在磁盤IO上。一些機(jī)制和配置指令可以減緩磁盤IO阻塞的場景。像sendfile和aio選項(xiàng)的組合為磁盤性能提供很大的空間。Nginx的安裝計(jì)劃,應(yīng)該要基于數(shù)據(jù)集、nginx可用的內(nèi)存數(shù)量、底層的存儲器架構(gòu)。

  • Worker 模型的另一個(gè)問題是:嵌入式script的有限支持

3.3進(jìn)程角色

一個(gè)master進(jìn)程,多個(gè)worker進(jìn)程,還有兩個(gè)特殊用途的進(jìn)程:cache loader和cache manager.在nginx 1.x版本中,所有的進(jìn)程的都是單線程的。進(jìn)程之間通信主要是通過共享內(nèi)存機(jī)制實(shí)現(xiàn)的,master作為根用戶運(yùn)行,其它進(jìn)程作為非特權(quán)用戶運(yùn)行。

3.3.1Master進(jìn)程

主要任務(wù):

  • 讀取,驗(yàn)證配置;
  • 創(chuàng)建,綁定,關(guān)閉sockets;
  • 開始,終止,維護(hù)已經(jīng)配置數(shù)量的workers;
  • 在不中斷服務(wù)情況下,重新加載配置;
  • 動態(tài)升級控制(開始新的,如果有必要可以回滾);
  • 重開log file;
  • 編譯嵌入的perl腳本;

3.3.2Worker 進(jìn)程

主要任務(wù):

  • 接收,加工處理來自client的連接;
  • 提供反向代理和過濾功能;
  • 做幾乎其它所有nginx力能所及的事件;

對于監(jiān)控nginx實(shí)例的行為,系統(tǒng)管理員應(yīng)該密切關(guān)注worker,因?yàn)樗鼈兎从沉藈eb服務(wù)器的實(shí)際日常操作的流程。

3.3.3Cache loader 進(jìn)程

負(fù)責(zé)檢查在磁盤上的緩存內(nèi)容,使用cache元數(shù)據(jù)構(gòu)建內(nèi)存數(shù)據(jù)庫。本質(zhì)上,它是準(zhǔn)備nginx實(shí)例去處理文件,這個(gè)文件已經(jīng)存儲在硬盤上的一個(gè)特定分配的目錄結(jié)構(gòu)中。遍歷這個(gè)目錄,檢查緩存內(nèi)容元數(shù)據(jù),修改內(nèi)存中相關(guān)聯(lián)的記錄,當(dāng)所有的事情被清理并準(zhǔn)備使用后,則退出。

3.3.4Cache manager 進(jìn)程

負(fù)責(zé)緩存過期和失效。在正常的nginx操作過程中,它會保存在內(nèi)存中,當(dāng)出現(xiàn)故障時(shí),master會重新啟動它。

3.4緩存系統(tǒng)

Nginx的緩存是以在文件系統(tǒng)上的分層數(shù)據(jù)存儲的形式實(shí)現(xiàn)。
緩存的keys是可配置的,不同特定的請求參數(shù)可以控制哪些數(shù)據(jù)被緩存。
緩存keys和緩存元數(shù)據(jù)被存儲在共享內(nèi)存塊中,cache loader和cache manager可以訪問這個(gè)共享內(nèi)存塊。Currently there is not any in-memory caching of files, other than optimizations implied by the operating system’s virtual filesystem mechanisms.每一個(gè)被緩存的響應(yīng)被放置在文件系統(tǒng)上的不同文件中。通過nginx 配置指令來實(shí)現(xiàn)分層(levels and naming details).當(dāng)響應(yīng)被寫到緩存目錄結(jié)構(gòu)中是,緩存文件的路徑和名稱將基于代理url的md5 hash值創(chuàng)建。

3.4.1內(nèi)存緩存的處理流程

內(nèi)存緩存的處理流程,如下:
當(dāng)nginx從上游服務(wù)讀取響應(yīng)時(shí),響應(yīng)內(nèi)容首先被寫到一個(gè)臨時(shí)文件,位于緩存目錄結(jié)構(gòu)之外;當(dāng)nginx完成請求處理時(shí),會重新命名臨時(shí)文件并且把它移動到緩存目錄中;如果臨時(shí)文件是在另外一個(gè)文件系統(tǒng)上,它會被復(fù)制,所以建議把臨時(shí)目錄和緩存目錄都在同一個(gè)文件系統(tǒng)上;當(dāng)臨時(shí)目錄和緩存目錄被清理時(shí),從緩存目錄結(jié)構(gòu)中刪除文件是也是非常安全的;nginx有第三方擴(kuò)展,可以遠(yuǎn)程控制緩存的內(nèi)存,計(jì)劃更多的工作在主發(fā)行版本中去集成這個(gè)功能。

響應(yīng)數(shù)據(jù)存儲在磁盤的文件系統(tǒng)中,響應(yīng)相關(guān)的元數(shù)據(jù)存儲在內(nèi)存中。
如果把所有的數(shù)據(jù)都放到內(nèi)存緩存,提高了訪問速度,但是內(nèi)存占用大。

3.5配置系統(tǒng)

Nginx配置系統(tǒng)啟發(fā)于Igor Sysoev對apache的經(jīng)驗(yàn)。他的主要觀點(diǎn)是一個(gè)可伸縮的配置系統(tǒng)對于web server是不可少的。遇到的主要的伸縮問題是當(dāng)對許多的virtual servers,directories,locations 和 datasets維護(hù)大量的復(fù)雜的配置時(shí)。在一個(gè)相對較大的web設(shè)置中,如果應(yīng)用程序和系統(tǒng)工程師自己都不能正確地完成,那么這將是一場噩夢。
因此,nginx配置系統(tǒng)的目的是簡化日常操作,并為web服務(wù)器配置的進(jìn)一步擴(kuò)展提供一種簡單的方法。
配置文件首先被master讀取并驗(yàn)證。worker只能讀取配置不能修改。
配置文件有多個(gè)不同的context 命令塊:main, http, server, upstream, location (and also mail for mail proxy)。

3.6內(nèi)部組件

Nginx 代碼庫包含:一個(gè)core,多個(gè)moudules.

3.6.1core

core提供nginx的基礎(chǔ),Web和mail反向代理功能;它使用網(wǎng)絡(luò)協(xié)議,構(gòu)建必要的運(yùn)行環(huán)境,確保不同模塊之間的無縫交互。但是特定的協(xié)議和特定的應(yīng)用特性是由moudule提供實(shí)現(xiàn),core不提供實(shí)現(xiàn)。

3.6.2module

在內(nèi)部,nginx通過module的pipeline or chain 來處理連接。換一句話說,對于每一個(gè)操作都有一個(gè)moudule來處理;比如:compression(壓縮)、修改內(nèi)容、連接上游服務(wù)器等。

有兩個(gè)nginx模塊位于核心模塊和真正的“功能”模塊之間:http and mail。
這兩個(gè)模塊在core 和 low-level 組件之間提供了抽象。它們包含了對各自的應(yīng)用層協(xié)議像http、smtp等事件的處理。

與core結(jié)合,這些上層模塊(http\mail)負(fù)責(zé)維護(hù)對各自的功能模塊調(diào)用的正確順序。然而http協(xié)議被實(shí)現(xiàn)作為http模塊的一部分,未來計(jì)劃把它分離到一個(gè)功能模塊中,因?yàn)樾枰С制渌膮f(xié)議like spdy。

功能模塊分為:event 模塊,phase hanlder, output filters,variable hanlders,protocols,upstreams和負(fù)載均衡器。這些模塊大多數(shù)都補(bǔ)充nginx 的http功能,然而event模塊和protocol也用于mail功能。Event 模塊提供了特定的依賴于操作系統(tǒng)的通知事件機(jī)制如kqueue or epoll.
Nginx 使用的event 模塊依賴操作系統(tǒng)的特性和構(gòu)建配置。Protocols 模塊允許nginx通過HTTPS, TLS/SSL, SMTP, POP3 and IMAP進(jìn)行通信。

一個(gè)典型的http請求處理周期如下:
1.客戶端發(fā)送http 請求;
2.Core模塊選擇合適的phase hanlder,它是通過location配置指定的用于請求匹配;
3.如果這樣配置,load balance選擇一個(gè)上游服務(wù)代理;
4.Phase hanlder 執(zhí)行任務(wù),并把output buffer 傳送到第一個(gè)filter;
5.第一個(gè)filter 傳送output buffer 到第二個(gè)filter;
6.第二個(gè)filter 傳送它到第三個(gè),以此類推;
7.最后響應(yīng)被傳送到客戶端;

Nginx 模塊調(diào)用是非常通用的。通過一系列的回調(diào)函數(shù)執(zhí)行,這些回調(diào)函數(shù)使用指針指向可執(zhí)行的函數(shù)。這樣做的缺點(diǎn)是當(dāng)程序員想要寫自己的模塊時(shí),會給他們帶來很大的負(fù)擔(dān),因?yàn)樗麄儽匦枰鞔_定義模塊應(yīng)該執(zhí)行的時(shí)間和方式。
為了減緩這種情況,nginx api和開發(fā)文檔已經(jīng)被改善并且更加可用。

在worker中,run-loop(響應(yīng)是在run-loop中生成創(chuàng)建的)中的動作,如下:
1.開始執(zhí)行ngx_worker_process_cycle();
2.使用操作系統(tǒng)特定的機(jī)制(如kqueue or epoll)處理事件;
3.接收事件,并分配相關(guān)聯(lián)的actions;
4.處理/代理 請求header and body;
5.生成響應(yīng)內(nèi)容(header,body),并傳送到客戶端;
6.完成請求;
7.Re-initialize timers and events.
The run-loop itself (steps 5 and 6) ensures incremental generation of a response and streaming it to the client.
處理http請求更加詳細(xì)的視圖可能 如下:
1.初始化請求處理;
2.處理header;
3.處理body;
4.調(diào)用相關(guān)的handler;
5.遍歷processing phases;

當(dāng)nginx處理http請求時(shí),會傳送請求經(jīng)過許多的processing phases。在每一個(gè)phase中會有一些hanlders調(diào)用。通常,phase hanlders 處理一個(gè)請求,并產(chǎn)生相應(yīng)的output。phase handlers被添加到locations(在配置文件被定義)。
Phase handlers 會做四件事情:get location 配置,生成適當(dāng)?shù)捻憫?yīng),send header,send body。一個(gè)handler有一個(gè)參數(shù):一個(gè)描述請求的特定的結(jié)構(gòu)。這個(gè)請求結(jié)構(gòu)中包含了client請求中許多有用的信息,例如請求method,uri,header。

當(dāng)讀取到http請求header時(shí),nginx查找相關(guān)的虛擬服務(wù)器配置。如果虛擬服務(wù)器找到,這個(gè)請求會經(jīng)過六個(gè)phase:
1.server rewrite phase;
2.Location phase;
3.Location rewrite phase(可以把請求帶回到上一個(gè)phase);
4.Access control phase;
5.Try_files phase;
6.Log phase;

嘗試在請求的響應(yīng)中生成必要的內(nèi)容,nginx把請求傳送到合適的內(nèi)容handler中。依賴明確的location配置,nginx首先嘗試無條件調(diào)用的handler,像perl,proxy_pass,flv,mp4等,如果這個(gè)請求不匹配上面內(nèi)容hanlders中的任何一個(gè),那么選擇下面handlers的一個(gè),明確的順序:random index,index,autoindex,gzip static,static.
在nginx文檔中可以找到indexing 模塊的明細(xì),然而這些模塊都是通過trailing slash(尾部斜杠/).如果一個(gè)特定的模塊像mp4 or autoindex 不合適,那么內(nèi)容會被當(dāng)作是一個(gè)文件or目錄,并且被static content handler 所提供。For a directory it would automatically rewrite the URI so that the trailing slash is always there (and then issue an HTTP redirect).

內(nèi)容handlers 的內(nèi)容被發(fā)送到filters.filters也是被添加到locations.一個(gè)location 可能 配置多個(gè)filters.filters對output(被一個(gè)handler 生成)操作,filters的執(zhí)行順序是編譯的時(shí)候指定的。對于開箱即用的filter是預(yù)定義的,對于第三方filters可以在構(gòu)建階段配置的,在現(xiàn)有的nginx實(shí)現(xiàn)中,filter僅可以改變出站。目前沒有提供機(jī)制去寫和添加filter轉(zhuǎn)換input內(nèi)容。
Input filter 會在未來的版本中出現(xiàn)。

Filters 遵循特殊的設(shè)計(jì)模式(filter模式)。一個(gè)filter被調(diào)用,開始執(zhí)行,調(diào)用下一個(gè)filter,直到chain中最后一個(gè)filter被調(diào)用。之后filters完成響應(yīng)。Filters不需要等待上一個(gè)filter完成。下一filter一旦取到上一個(gè)filter的input就可以開始執(zhí)行工作。在來自上游服務(wù)的全部的響應(yīng)被接收之前,生成的響應(yīng)可以被發(fā)送到client.

有header filter and body filter。nginx會把響應(yīng)的header和body放到相應(yīng)的獨(dú)立的filter中。
Header filter包含三個(gè)基本的步驟:
1.決定是否對這個(gè)響應(yīng)進(jìn)行操作(decide whether to operate on the response);
2.對這個(gè)響應(yīng)進(jìn)行操作;
3.調(diào)用下一個(gè)filter;

Body filter 轉(zhuǎn)換生成的內(nèi)容,包含的動作:
?server-side includes
?XSLT filtering
?image filtering (for instance, resizing images on the fly)
?charset modification
?gzip compression
?chunked encoding
Filter chain 處理完之后,響應(yīng)被傳送到writer.連同writer有兩個(gè)額外的特定用途的filter:copy filter,postpone filter.
Copy filter負(fù)責(zé)把相關(guān)響應(yīng)的內(nèi)容(可能被存儲在一個(gè)代理的臨時(shí)目錄中)填充的內(nèi)存 buffer中。
Postpone filter應(yīng)用于subrequests.
Subrequests對于request/response處理是非常重要的機(jī)制。Subrequests也是nginx最強(qiáng)大方面之一。使用子請求,nginx可以從與client最初請求的URL不同的URL返回結(jié)果.一些web 框架調(diào)用內(nèi)部重定向。然而,filters不僅可以執(zhí)行多個(gè)subrequests和整合outpus到單個(gè)response中,而且subrequest也可以是內(nèi)嵌和分層的。一個(gè)subrequest可以執(zhí)行它自己的subrequests,并且一個(gè)sub-subrequest可以發(fā)起sub-sub-subrequests.subrequests可以映射到硬盤上的文件,其它的handlers,or 上游servers.subrequest大多用于insert 額外的內(nèi)容(基于最初的response的data).例如,ssi(server-side include)模塊使用filter解析返回的document的內(nèi)容,而且使用指定的urls的內(nèi)容替換include directives.又或者比如,創(chuàng)建一個(gè)filter,把document 的全部內(nèi)容當(dāng)作是要重新取回的url,并append 這個(gè)新的文檔到url它自己。

Upstream和load balancers模塊也值得簡要描述。Upstreams被用于實(shí)現(xiàn)什么可以被識別為一個(gè)content hanlder,它是一個(gè)反向代理(proxy_pass handler).
Upstream 模塊主要準(zhǔn)備把請求發(fā)送到一個(gè)upstream server (or backend),并接收來自upstream server的響應(yīng)。這里沒有對output filter的調(diào)用。
Upstream做的事情是:設(shè)置callbacks,以便在write和read upstream時(shí)被調(diào)用。Callback實(shí)現(xiàn)的功能,如下:
1.制作一個(gè)request buffer(or a chain of them)發(fā)送到upstream server.
2.重新初始化/重置upstream server的連接(再次創(chuàng)建請求之前發(fā)生)。
3.處理upstream響應(yīng)的第一部分,并保存從upstream server接收的payloads的指針。
4.中止請求(當(dāng)client貿(mào)然中止時(shí));
5.當(dāng)nginx完成upstream server的讀取時(shí),結(jié)束請求;
6.整理response body;

當(dāng)多于一個(gè)upstream server符合條件時(shí),load balancer 通過proxy_pass hanlder 去選擇一個(gè)upstream server.A load balancer registers an enabling configuration file directive,提供額外的upstream 初始化功能(解析dns中upstream names等),初始化連接結(jié)構(gòu),request路由的判定,修改統(tǒng)計(jì)信息。目前,nginx對于upstream servers的load balance提供了兩個(gè)標(biāo)準(zhǔn)的算法:round-robin,ip-hash.

Upstream 和load balancing 處理機(jī)制包含一些算法:探測失敗的upstream servers,重新路由新的請求到剩下的upstream servers(這些是沒有失敗的),然而計(jì)劃了很多工作去加強(qiáng)這個(gè)功能。通常,對load balancer計(jì)劃了更多的工作,在nginx的下個(gè)版本中,跨不同的upstream servers分配load的機(jī)制和health checks 將會極大地被改善。

有兩個(gè)別的有意思的模塊,在配置文件中,它們提供了額外的變量集去使用。當(dāng)nginx的變量被創(chuàng)建和跨不同的模塊被修改時(shí),有兩個(gè)專用的模塊用于變量:geo,map.geo模塊用于促進(jìn)client的跟蹤,基于client的ip 地址。這個(gè)模塊可以創(chuàng)建任意的變量,這些變量依賴于client的ip地址。Map module allows for the creation of variables from other variables,實(shí)際上是提供了hostnams和別的運(yùn)行變量的靈活映射。這種module可以被稱為variable hanlder.

在單個(gè)nginx worker中實(shí)現(xiàn)的內(nèi)存分配機(jī)制,在一些程度上是受到apache的啟發(fā)。Nginx內(nèi)存管理高層次描述,如下:
對每一個(gè)連接,必要的內(nèi)存buffers是動態(tài)分配,連接,存儲和操作request和response的header和body,并且在連接release時(shí)釋放。注意這一點(diǎn)很重要,nginx 盡可能的avoid復(fù)制內(nèi)存中的data,并且大部分?jǐn)?shù)據(jù)是通過指針值傳遞的,而不是通過調(diào)用memcpy.

深入一點(diǎn),當(dāng)response被一個(gè)module生成時(shí),取到的內(nèi)容被放入一個(gè)內(nèi)存buffer,這個(gè)buffer被增加到一個(gè)buffer chain link中。Subrequest 使用這個(gè)buffer chain link處理工作。在nginx中,buffer chain非常復(fù)雜,因?yàn)橛卸鄠€(gè)處理場景,依賴于module type 而不同。例如,當(dāng)實(shí)現(xiàn)一個(gè)body filter module時(shí),精確地管理buffer是非常棘手的.這樣一個(gè)module同時(shí)只能操作buffer chain中的一個(gè)buffer,并且需要判斷是否overwrite input buffer,是否使用新分配的buffer替換舊的buffer,或者在這個(gè)buffer出問題之前或者出問題之后,insert 一個(gè)新的buffer.更為復(fù)雜的事情是,有時(shí)一個(gè)module將會接收多個(gè)buffer,所以這個(gè)module會有一個(gè)不完整的buffer chain(module必需對它操作)。然而,這時(shí)nginx只提供了一個(gè)low-level api去操作這個(gè)buffer chain,所以任何第三方module實(shí)現(xiàn)之前,開發(fā)者應(yīng)該要非常熟悉nginx的這神秘的部分。
根據(jù)以上的方式,需要注意的是,內(nèi)存buffer被分配到連接的整個(gè)生命周期,因此長連接會保留一些額外的內(nèi)存。同時(shí),在閑置的keepalive連接上,nginx只使用550 bytes內(nèi)存。Nginx未來的發(fā)布版本可能會優(yōu)化:對于長連接,重用和共享內(nèi)存buffer.

Nginx pool allocator管理內(nèi)存分配。共享內(nèi)存被用于接收mutex,cache元數(shù)據(jù),ssl session cache以及與帶寬監(jiān)控和管理相關(guān)的信息。Nginx實(shí)現(xiàn)了一個(gè)slab分配器來管理共享內(nèi)存分配。允許同時(shí)安全地使用共享內(nèi)存,一些鎖機(jī)制是可用的(mutex and semophore).為了組織復(fù)雜的數(shù)據(jù)結(jié)構(gòu),nginx還提供了一個(gè)red-black 樹實(shí)現(xiàn)。Red-black tree 用于在共享內(nèi)存中保留cache元數(shù)據(jù),
跟蹤不是正則表達(dá)式(non-regex)的location 定義和處理一些其它的任務(wù)。

不幸的是,上述所有內(nèi)容從未以一致和簡單的方式描述過,為nginx開發(fā)第三方擴(kuò)展是非常復(fù)雜的。但是在nginx內(nèi)部存在一些好的文檔。

不管與第三方開發(fā)相關(guān)的困難,nginx用戶社會目前出現(xiàn)了許多的第三方modules.for instance, an embedded Lua interpreter module for nginx, additional modules for load balancing, full WebDAV support, advanced cache control and other interesting third-party work that the authors of this chapter encourage and will support in the future.

4工作流程

總結(jié)

以上是生活随笔為你收集整理的Nginx 架构原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。