openresty開發系列31--openresty執行流程
咱們先看個例子
location /test {
set $a 32;
echo $a;
set $a 56;
echo $a;
}
echo nginx第三方模塊,是用於作響應輸出
輸出了 56
Nginx 處理每個用戶請求時,都是按照若干個不一樣階段依次處理的。而不是根據配置文件上的順序。
之上的例子 涉及到了 兩個階段 rewrite和content階段
set屬於rewrite階段
echo屬於content階段
並且 rewrite階段的指令 在 content階段指令 以前執行。
實際的執行順序應當是
set $a 32;
set $a 56;
echo $a;
echo $a;
因此輸出 56
在咱們配置文件中執行的指令,能夠理解爲對咱們的執行階段進行入棧
Nginx處理請求的過程一共劃分爲11個階段,按照執行順序依次是post-read、server-rewrite、
find-config、rewrite、post-rewrite、 preaccess、access、post-access、try-files、content、log.
一、post-read
讀取請求內容階段,nginx讀取並解析完請求頭以後就當即開始運行;
例如模塊 ngx_realip 就在 post-read 階段註冊了處理程序,
它的功能是迫使 Nginx 認爲當前請求的來源地址是指定的某一個請求頭的值。
二、server-rewrite
server請求地址重寫階段;當ngx_rewrite模塊的set配置指令直接書寫在server配置塊中時,
基本上都是運行在server-rewrite 階段
三、find-config
配置查找階段,這個階段並不支持Nginx模塊註冊處理程序,
而是由Nginx核心來完成當前請求與location配置塊之間的配對工做。
四、rewrite
location請求地址重寫階段,當ngx_rewrite指令用於location中,就是再這個階段運行的;
另外ngx_set_misc(設置md五、encode_base64等)模塊的指令,
還有ngx_lua模塊的set_by_lua指令和rewrite_by_lua指令也在此階段。
五、post-rewrite
請求地址重寫提交階段,當nginx完成rewrite階段所要求的內部跳轉動做,若是rewrite階段有這個要求的話;
六、preaccess
訪問權限檢查準備階段,ngx_limit_req和ngx_limit_zone在這個階段運行,
ngx_limit_req能夠控制請求的訪問頻率,ngx_limit_zone能夠控制訪問的併發度;
七、access
訪問權限檢查階段,標準模塊ngx_access、第三方模塊ngx_auth_request以及第三方模塊ngx_lua的access_by_lua
指令就運行在這個階段。配置指令可能是執行訪問控制相關的任務,如檢查用戶的訪問權限,檢查用戶的來源IP是否合法;
八、post-access
訪問權限檢查提交階段;主要用於配合access階段實現標準ngx_http_core模塊提供的配置指令satisfy的功能。
satisfy all(與關係),satisfy any(或關係)
九、try-files
配置項try_files處理階段;專門用於實現標準配置指令try_files的功能,
若是前 N-1 個參數所對應的文件系統對象都不存在,
try-files 階段就會當即發起「內部跳轉」到最後一個參數(即第 N 個參數)所指定的URI.
十、content
內容產生階段,是全部請求處理階段中最爲重要的階段,
由於這個階段的指令一般是用來生成HTTP響應內容並輸出 HTTP 響應的使命;
十一、log
日誌模塊處理階段;記錄日誌
NGX_HTTP_POST_READ_PHASE:
#讀取請求內容階段
NGX_HTTP_SERVER_REWRITE_PHASE:
#Server請求地址重寫階段
NGX_HTTP_FIND_CONFIG_PHASE:
#配置查找階段:
NGX_HTTP_REWRITE_PHASE:
#Location請求地址重寫階段,經常使用
NGX_HTTP_POST_REWRITE_PHASE:
#請求地址重寫提交階段
NGX_HTTP_PREACCESS_PHASE:
#訪問權限檢查準備階段
NGX_HTTP_ACCESS_PHASE:
#訪問權限檢查階段,經常使用
NGX_HTTP_POST_ACCESS_PHASE:
#訪問權限檢查提交階段
NGX_HTTP_TRY_FILES_PHASE:
#配置項try_files處理階段
NGX_HTTP_CONTENT_PHASE:
#內容產生階段 最經常使用
NGX_HTTP_LOG_PHASE:
#日誌模塊處理階段 經常使用
到此,應該明白Nginx 的conf中指令的書寫順序和執行順序是兩碼事,切記。
有些階段是支持 Nginx 模塊註冊處理程序,有些階段並不能夠。
最經常使用的是 rewrite階段,access階段 以及 content階段;
不支持 Nginx 模塊註冊處理程序的階段 find-config, post-rewrite, post-access,
主要是 Nginx 核心完成本身的一些邏輯。
Nginx下Lua處理階段與使用範圍
openresty發起一個請求時,會有相應的執行流程
如圖
從圖中可知,OpenResty 處理請求大體分爲四個階段:
1)初始化階段(Initialization Phase)
2)重寫與訪問階段(Rewrite / Access Phase)
3)內容生成階段(Content Phase)
4)日誌記錄階段(Log Phase)
咱們OpenResty作個測試,示例代碼以下:
init_by_lua 'ngx.log(ngx.ERR, "init_by_lua")';
init_worker_by_lua 'ngx.log(ngx.ERR, "init_worker_by_lua")';
server {
listen 80;
location /exec {
rewrite_by_lua 'ngx.log(ngx.ERR, "rewrite_by_lua")';
set_by_lua $a 'ngx.log(ngx.ERR, "set_by_lua")';
access_by_lua 'ngx.log(ngx.ERR, "access_by_lua")';
header_filter_by_lua 'ngx.log(ngx.ERR, "header_filter_by_lua")';
body_filter_by_lua 'ngx.log(ngx.ERR, "body_filter_by_lua")';
log_by_lua 'ngx.log(ngx.ERR, "log_by_lua")';
content_by_lua 'ngx.log(ngx.ERR, "content_by_lua")';
}
}
這幾個階段的存在,應該是openresty不一樣於其餘多數Web server編程的最明顯特徵了。
因爲nginx把一個會話分紅了不少階段,這樣第三方模塊就能夠根據本身行爲,掛載到不一樣階段進行處理達到目的。
這樣咱們就能夠根據咱們的須要,在不一樣的階段直接完成大部分典型處理了。
指令能夠在http、server、server if、location、location if幾個範圍進行配置:
指令 所到處理階段 使用範圍 解釋
init_by_lua
init_by_lua_file loading-config http
nginx Master進程加載配置時執行;一般用於初始化全局配置/預加載Lua模塊
init_worker_by_lua
init_worker_by_lua_file starting-worker http
每一個Nginx Worker進程啓動時調用的計時器,若是Master進程不容許則只會在init_by_lua以後調用;
一般用於定時拉取配置/數據,或者後端服務的健康檢查
set_by_lua
set_by_lua_file rewrite server,server if,location,location if
設置nginx變量,能夠實現複雜的賦值邏輯;此處是阻塞的,Lua代碼要作到很是快;
rewrite_by_lua
rewrite_by_lua_file rewrite tail http,server,location,location if
rrewrite階段處理,能夠實現複雜的轉發/重定向邏輯;
access_by_lua
access_by_lua_file access tail http,server,location,location if
請求訪問階段處理,用於訪問控制
content_by_lua
content_by_lua_file content location,location if
內容處理器,接收請求處理並輸出響應
header_filter_by_lua
header_filter_by_lua_file output-header-filter http,server,location,location if
響應 HTTP過濾處理(例如添加頭部信息),設置header和cookie
body_filter_by_lua
body_filter_by_lua_file output-body-filter http,server,location,location if
響應 BODY過濾處理(例如完成應答內容統一成大寫) 對響應數據進行過濾,好比截斷、替換。
log_by_lua
log_by_lua_file log http,server,location,location if
響應完成後本地異步完成日誌記錄(日誌能夠記錄在本地,還能夠同步到其餘機器)
階段處理,好比記錄訪問量/統計平均響應時間
實際上咱們只使用其中一個階段content_by_lua,也能夠完成全部的處理。但這樣作,
會讓咱們的代碼比較臃腫,越到後期愈加難以維護。把咱們的邏輯放在不一樣階段,分工明確,代碼獨立nginx