Nginx的執行階段詳解

在了解nginx的執行階段前,先看一個例子

圖片

對echo不熟悉的,可以先看文章Nginx調試必備了解下echo擴展

?

回到上面這個例子,在server塊中配置這樣的location,你覺得輸出是什么樣子?

?

按照正常的邏輯,輸出應該是32 56,我們請求下,看下nginx處理的結果

圖片

?

兩次輸出都是56,顛覆認知。這就是因為set和echo處在nginx不同的執行階段,在nginx中,處在不同階段的配置,和配置文件順序沒有任何關系

?

Nginx處理請求過程總共劃分為11個階段,按順序依次是post-read、server-rewrite、find-config、rewrite、post-rewrite、preaccess、access、post-access、precontent、content以及log

?

看一下nginx源碼中的定義,在http/ngx_http_core_module.h中

圖片

我這里是1.17.7版本的nginx,我看了nginx1.16.0版本一樣,老一點的版本內容預處理階段是try_files階段

?

下面結合測試詳細說一下每個階段

圖片

?

post-read 階段

?

圖片

?

該階段是nginx接收完請求頭之后的第一個階段,它位于uri重寫之前,該階段很少用,很少有模塊會注冊在該階段,默認情況下,該階段被跳過,但是有個兩個標準函數是注冊在這個階段的,set_real_ip_from、real_ip_header

?

看到real_ip有沒有很熟悉,通常nginx日志或者后端需要獲取客戶端真實IP的時候,需要把cdn或者你前端的nginx或者代理的ip改寫之后來獲取,就會用到這個,下面看例子

?

圖片

?

通過curl -H添加header頭請求,然后查看結果

圖片

?

通常多級代理,后端要獲取真實IP就是通過這種自定義header的方式去獲取

?

圖片

?

server-rewrite 階段

?

圖片

?

該階段是server級別的uri重寫階段,該階段執行處于server塊內,location塊外的重寫指令,在讀取請求頭的過程中nginx會根據host及端口找到對應的虛擬主機配置

?

該階段不只是執行rewrite指令,通常該階段包含標準函數ngx_rewrite、set,看例子

?

圖片

?

這里在server塊內,location塊外set一個變量$a,在location中引用,因為server-rewrite階段在前面,所以$a變量會先賦值,查看結果

圖片

?

圖片

?

find-config 階段

?

圖片

?

該階段是尋找location配置階段,該階段使用重寫之后的uri來查找對應的location,如果匹配到的location中有重寫指令的話,該階段會再次執行,直到匹配到最終的location

?

這個階段的匹配工作是由nginx核心模塊來完成的,并不支持nginx模塊注冊處理程序

?

這個階段不太好整例子,想來想去沒有想到可以體現的例子,但是debug日志可以體現,用上一個階段的例子的請求日志看下

?

圖片

?

很直觀,在執行完上個階段的set $a之后,就開始匹配location,最終匹配到test,接著執行下面的階段

?

圖片

?

rewrite 階段

?

圖片

?

該階段是location級別的uri重寫階段,該階段執行location基本的重寫指令,同樣也可能被指定多次

?

直接寫個跳轉看日志

圖片

?

通過curl -L跟隨跳轉請求看下結果

圖片

?

查看debug日志

圖片

?

仍然是先執行server塊內的set,之后匹配到rewrite的location,然后執行location內的rewrite

?

圖片

?

post-rewrite階段

?

圖片

?

該階段是location級別重寫的后一個階段,用來檢查上階段是否有uri重寫,并根據結果跳轉到合適的階段

?

這個階段緊接上一個階段,是由nginx核心完成rewrite階段所要求的跳轉,即內部跳轉

?

內部跳轉本質上其實就是把當前的請求處理階段跳回到find-config階段,類似于條件分支循環,這也就是上面說到find-config階段會被多次執行的原因。把上階段的rewrite請求跳轉到find-config階段,重新進行請求uri和location配置塊的配對,這個過程可以從上面階段的后續debug日志可以看出來

?

圖片

rewrite被改寫到test,然后開始重新匹配uri為test的location

?

圖片

接著執行find-config階段的匹配過程,然后執行后面的階段

?

圖片

?

preaccess 階段

?

圖片

?

該階段是訪問權限控制的前一階段,預控制階段。該階段在權限控制階段之前,一般也用于訪問控制,比如limit的限制速率、限制連接數等

?

該階段包含的標準函數ngx_limit_req、ngx_limit_zone等

?

實例結合后面的下個階段一起看

?

圖片

?

access 階段

?

圖片

?

該階段是權限訪問控制階段,比如基于IP黑白名單的權限控制,基于用戶名密碼的權限控制等

?

該階段包含的標準函數ngx_access、ngx_auth_request函數等

?

結合preaccess,我們在同一個location中配置limit和access,如下

圖片

?

然后請求access看下結果

圖片

?

看下debug日志,分析處理階段

圖片

?

先處理limit,然后接著處理access部分

圖片

?

post-access 階段

?

圖片

?

該階段是訪問控制的后一階段,和post-rewrite階段類似,不支持nginx模塊注冊處理程序,由nginx核心自己完成處理工作,主要是配合access階段實現后續處理

?

這里常用的指令是satisfy,它的功能類似if判斷中的“與”、“或”關系,在access階段可以注冊多個nginx模塊,比如上面提到的access模塊和auth認證模塊,如果兩個模塊都注冊了,那么是執行哪個?按哪個匹配結果來執行,這個時候就用到satisfy,它就是讓多個控制之間彼此協作

?

比如上面兩個模塊都在access階段注冊了與訪問控制相關的處理程序,那就有兩種協作方式,一是模塊access和auth都通過驗證才算通過,另外一種是只要其中任一通過驗證就算通過。第一種方式為all方式,也就是“與”關系,第二種方式為any方式,也就是“或”關系,默認情況下nginx使用的是all方式

?

圖片

?

precontent 階段

?

圖片

?

該階段為生成內容的前一階段,主要是用于處理try_files指令的配置,如果沒有配置try_files指令,這個階段會跳過,該階段不支持nginx模塊注冊處理程序

?

try_files指令接受兩個以上任意數量的參數,每個參數都指定一個uri,比如設置N個參數,nginx會在precontent階段依次把前N-1個參數映射為文件系統上的文件或目錄,逐個檢查這些文件或目錄是否存在。一旦Nginx匹配到某個文件或目錄存在,就會在precontent階段,把當前請求的uri改寫為該對象所對應的參數uri,如果前N-1個參數所對應的文件或目錄都不存在,則precontent階段會發起內部跳轉,按照最后一個參數所指定的uri進行find-config階段

?

配置個try_files來看下執行過程

圖片

?

請求try,看下結果

圖片

并沒有執行echo uri部分,而是到test的location了,看下debug日志

?

圖片

可以看到和我們上面說的結果一致

?

圖片

?

content 階段

?

圖片

?

該階段是所有階段中最重要的一個階段,該階段負責內容生成,并輸出http響應。通過nginx配置文件中的配置指令,生成響應內容,返回給客戶端,這個階段的配置指令例如echo、proxy_pass等

?

日志體現該階段

圖片

?

?

圖片

?

log 階段

?

圖片

?

?該階段就是日志記錄階段,根據log配置寫入日志文件,比如log級別,日志格式logformat等,包含nginx的access_log和error_log等

?

在debug日志中也有記錄

圖片

請求返回給客戶端后,記錄日志,然后保持keepalive,如果是不需要keepalive的時候,直接close連接

?

以上就是nginx處理請求的11個階段,熟悉之后,對nginx的了解更深

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/535404.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/535404.shtml
英文地址,請注明出處:http://en.pswp.cn/news/535404.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Docker掛了,數據如何找回

docker在實際使用中,讓運維人員詬病的,除了安全問題外,大概就是數據的問題了 很多人在初用docker的時候,很多時候都忘記或不知道docker中需要保留的數據需要掛載到宿主機文件夾到容器內部對應目錄(當然除了掛載宿主機目…

TCP總結

TCP這些東西,基本每個程序猿都或多或少是掌握的了。雖然感覺在實際開發中沒有什么用武之處,但,面試他要問啊 而最近大家伙過完年,也都在準備春招,我也一樣。閱讀了一些okHttp源碼之后,又屁顛屁顛地跑回來重…

Shell 中各種括號的作用

一、小括號,圓括號() 1、單小括號 () ①命令組。括號中的命令將會新開一個子shell順序執行,所以括號中的變量不能夠被腳本余下的部分使用。括號中多個命令之間用分號隔開,最后一個命令可以沒有分號,各命令和…

linux基線核查腳本

#!/bin/bash #version 2.0cat <<EOF ************************************************************************************* ***** linux基線檢查腳本 ***** ************************************************************************************* *…

LDAP命令介紹---dsreplication

可以使用此實用程序來配置服務器之間的復制, 以使服務器數據保持同步。要正確進行復制, 必須先使用 enable 子命令啟用復制, 然后再使用 initialize 子命令將一個服務器的內容初始化為另一個服務器的內容用法: dsreplication {子命令} {選項}可用子命令:disable對指定服務器中…

LDAP命令介紹---dsconfig

此實用程序可用于定義目錄服務器的基本配置 用法: dsconfig {子命令} {選項} 獲取子命令用法列表: --help-distribution 顯示與 分發 相關的子命令 --help-general-configuration 顯示與 一般配置 相關的子命令 --help-integration 顯示與 集成 相關的子命令 --…

LDAP命令介紹---dsconfig子命令----help-distribution顯示與分發相關的子命令

此實用程序可用于定義目錄服務器的基本配置用法: dsconfig {子命令} {選項}可用子命令:create-distribution-algorithm創建分發算法create-distribution-partition創建分發分區create-workflow-element --type distribution創建分發工作流元素create-global-index創建全局索引…

LDAP命令介紹---ldappasswordmodify口令修改操作

此實用程序可用于在目錄服務器中執行 LDAP 口令修改操作用法: ldappasswordmodify {選項}其中 {選項} 包括:-a, --authzID {authzID}應更改口令的用戶條目的授權 ID -A, --provideDNForAuthzID將綁定 DN 用作口令修改操作的授權 ID -n, --newPassword {newPassword}為目標用戶…

LDAP命令介紹---dstune

此實用程序可用于幫助您優化 OUD 目錄服務器。 您可以選擇自動或基于其他標準 (例如, 內存限制或服務器將包含的數據) 優化服務器用法: dstune {子命令} {選項}可用子命令:data-based使用描述目錄服務器將包含的數據的信息優化服務器。使用 --ldifFile 可基于 LDIF 文件的內容…

LDAP命令介紹---dsreplication--initialize

initialize 將目標服務器中指定基礎 DN 下的數據內容初始化為源服務器的內容。要正確進行復制, 在啟用復制后必須執行該操作 (也可以使用 initialize-all 達到該目的) initialize-all 對于正在復制其內容的所有服務器, 將它們指定基礎 DN 下的數據內容初始化為指定…

LDAP命令介紹---dsreplication--enable:DISABLE

enable 用法: dsreplication enable {選項} 更新服務器的配置以復制指定基礎 DN 下的數據。如果某個指定的服務器正在復制其他服務器中基礎 DN 下的數據, 執行此子命令將會更新所有服務器的配置 (因此, 對于每個添加到復制拓撲中的服務器, 將都能執行一次命令行)全局選項:請參…

LDAP命令介紹---import-ldif

[oracleoud bin]$ ./import-ldif --help 此實用程序可用于將 LDIF 數據導入目錄服務器后端用法: import-ldif {選項}其中 {選項} 包括:-l, --ldifFile {ldifFile}要導入的 LDIF 文件的路徑 -A, --templateFile {templateFile}用于生成導入數據的 MakeLDIF 模板的路徑 -a, --ap…

LDAP命令介紹---verify-index--驗證索引

[oraclelocalhost bin]$ ./verify-index -b "DCCOM" telephoneNumber 在解析命令行參數時出現錯誤: 參數 "telephoneNumber" 沒有以一個或兩個破折號開頭, 并且不允許未命名的結尾參數 此實用程序可用于確保基于 Berkeley DB Java Edition 的后端中的索引…

LDAP----manage-account

[oraclelocalhost bin]$ ./manage-account -D "cndirectory manager" -j pwd-file get-all \ > > --targetDN uidkvaughan,ouPeople,dcexample,dccom 在解析命令行參數時出現錯誤: 無法接受為參數 -j 提供的值 "pwd-file": 為參數 bindpwfile 指定…

LDAP組的概念以及命令

Oracle統一目錄支持組&#xff0c;組是作為單個對象管理的條目集合。通常&#xff0c;目錄管理員配置打印機組、軟件應用程序組、員工組等。在為一組用戶分配特殊訪問權限時&#xff0c;組尤其有用。例如&#xff0c;您可以配置一組訪問管理器&#xff0c;并分配權限&#xff0…

oracle中修改process

可以用如下命令查看數據庫連接的消耗情況 select b.MACHINE, b.PROGRAM, b.USERNAME, count(*) from v$process a, v$session b where a.ADDR b.PADDR and b.USERNAME is not null group by b.MACHINE, b.PROGRAM, b.USERNAME order by count(*) desc 在 oracle中&…

V$LICENSE表結構

V$LICENSE V$LICENSE 顯示有關許可限制的信息。 列名 數據類型 描述 SESSIONS_MAX NUMBER 實例允許的最大并發用戶會話數 SESSIONS_WARNING NUMBER 實例的并發用戶會話的警告限制 SESSIONS_CURRENT NUMBER 當前并發用戶會話數 SESSIONS_HIGHWATER NUMBER 自實…

升級ssl和ssh

#/bin/bash#需要手動修改的變量 version"ssh_8.6p1" #定義版本號 soft_dir$(cd "$(dirname "$0")"; pwd) # 上傳安裝包的目錄 ssl_media"openssl-1.1.1k.tar.gz" #ssl軟件包名 ssh_media"openssh-8.6p1.tar.gz" # ssh軟件…

zabbix5.2安裝-linux

一.編譯安裝httpd1.刪除舊版httprpm -qa | grep httpd rpm -e --nodeps rpm -qa | grep httpd find / -name httpd --delete find / -name httpd -help find / -name httpd -exec rm -rf {} \; 2.安裝httpd-2.4.38.tar.gz http://httpd.apache.org/download 安裝apr-1.6.2.…

安裝python3.9

GCC版本 這個版本的編譯器不適合編譯Python3.9&#xff0c;在編譯時會產生如下的錯誤。我們用這個老版本編譯器編譯一個新的GCC 9.2版。 Could not import runpy module Traceback (most recent call last):File "Python-3.8.1/Lib/runpy.py", line 15, in <mod…