摘要:OpenResty 是國人開發的一個基于 Nginx 的可伸縮的 Web 平臺,可以使用 Lua 腳本語言調動 Nginx 支持的各種 C 以及 Lua 模塊,解決了高并發的痛點,Nginx是使用異步事件模型,而 lua 可以用傳統的同步編程思想上在 nginx 請求接進來后處理稍復雜的邏輯,
目錄
- OpenResty 基礎
- OpenResty 原理
- OpenResty 執行階段
- OpenResty 執行階段總結
- OpenResty 執行階段詳解
- 1、init_by_lua_*
- 2、init_worker_by_lua_*
- 3、set_by_lua_*
- 4、rewrite_by_lua\_* 、access_by_lua\_* 和 content_by_lua_*
- 5、balancer_by_lua_*
- 6、header_filter_by_lua\_* 和 body_filter_by_lua\_*
- 7、log_by_lua_*
OpenResty 基礎
OpenResty 原理
Nginx 采用的是 master-worker 模型,一個 master 行程管理多個 worker 行程,基本的事件處理都是放在 woker 中,master 負責一些全域初始化,以及對 worker 的管理,
在OpenResty中,每個 woker 使用一個 LuaVM,當請求被分配到 woker 時,將在這個 LuaVM 里創建一個 coroutine(協程),協程之間資料隔離,

OpenResty 執行階段
OpenResty將應用分為4個大階段,11個小階段,如下圖所示,
初始化階段: master行程啟動預加載/生成worker行程預加載
轉發/訪問階段:url轉發,權限判斷
內容處理/生成階段: 內容生成
日志階段: 日志記錄

OpenResty 執行階段總結
- 注:以下所有指令均在 nginx.conf 檔案里撰寫
| 階段 | 概述 |
|---|---|
| init_by_lua_* | Nginx 加載組態檔時執行 |
| init_worker_by_lua_* | 每個 worker 行程被創建時執行 |
| set_by_lua_* | 初始化Nginx變數 |
| rewrite_by_lua* | 轉發、URL重定向、快取、子請求、控制頭等功能 |
| access_by_lua* | IP 準入、介面權限等情況集中處理(例如完成簡單防火墻) |
| content_by_lua* | 內容生成,執行業務邏輯并產生相應 |
| header_filter_by_lua* | 回應頭部過濾處理(例如添加頭部資訊) |
| body_filter_by_lua* | 回應體過濾處理(例如完成應答內容統一成大寫) |
| log_by_lua* | 會話完成后本地異步完成日志記錄(日志可以記錄在本地,還可以同步到其他機器) |
OpenResty 執行階段詳解
1、init_by_lua_*
使用方法:
init_by_lua_block {lua-script-str } 或
init_by_lua_file LuaSrc/init/init.lua; # 和init_by_lua_block作用一樣,只是在將代碼直接放到 init.lua 檔案里
執行階段:loading-config
當 Nginx 的 master 行程加載 Nginx 組態檔會執行指定的代碼,每當 Nginx 獲得 Hangup 多載信號加載行程時代碼都會被重新執行,該階段一般會初始化lua全域變數、預加載模塊、初始化 lua_shared_dict 共享記憶體資料
可以使用的 lua API 指令:ngx.log、ngx.shared.DICT、print
2、init_worker_by_lua_*
使用方法:
init_worker_by_lua_block {lua-script-str } 或
init_worker_by_lua_file filepath
執行階段:starting-worker
當 master 行程被啟動后,每個 worker 行程被創建時都會執行這段 lua 代碼,該階段最常見的功能是執行定時任務,也可以實作后端健康檢查功能,用于檢測后端HTTP服務器是否正常,
3、set_by_lua_*
使用方法:
set_by_lua_block $res { lua-script-str } 或
set_by_lua_file $res filepath
執行階段:rewrite
這里主要用于設定一些nginx變數,rewrite 階段是 location 請求地址重寫階段,位于location中的 ngx_rewrite 指令就是在這個階段運行,set_by_lua_* 指令塊在 Nginx 中是阻塞操作,不支持非阻塞I/O,盡量在這個階段執行短少代碼,
禁用的 lua API :
輸出型別的API函式(如ngx.say和ngx.send_headers),
控制型別的API函式(如ngx.exit),
子請求的API函式(如ngx.location.capture和ngx.location.capture_multi),
Cosocket API函式(如ngx.socket.tcp和ngx.req.socket),
休眠API函式ngx.sleep,
4、rewrite_by_lua_* 、access_by_lua_* 和 content_by_lua_*
使用方法:
rewrite_by_lua_block { lua-script-str } 或
rewrite_by_lua_file filepathaccess_by_lua_block { lua-script-str } 或
access_by_lua_file filepathcontent_by_lua_block { lua-script-str } 或
content_by_lua_file filepath
執行階段分別是:rewrite tail、access tail、content
以上指令分別在 rewrite tail / access tail / content 階段對每個請求都會執行設定的 lua 代碼,這些 lua 代碼可以呼叫所有的 lua API ,并運行在獨立的 lua 虛擬機上,以新的協程來執行,
rewrite_by_lua_* :可以實作對請求 URL 進行重定向、讀取 MySQL 或 Redis 資料、發送子請求、控制請求頭等,
access_by_lua_* :處理一些請求,一般用來進行權限檢查和黑白名單配置,完成簡單的防火墻,
content_by_lua_* :執行業務邏輯并產生相應,指令不可以和其他內容處理階段的模塊如echo、return、proxy_pass等放在一起,
5、balancer_by_lua_*
使用方法:
balancer_by_lua_block { lua-script-str } 或
balancer_by_lua_file filepath
執行階段:content
在upstream的配置中執行并控制后端服務器的地址,它會忽視原upstream中默認的配置,Lua代碼的執行環境不支持yield,因此需禁用可能會產生yield的Lua API指令,但可以利用ngx.ctx創建一個擁有背景關系的變數,在本階段前面的某個執行階段(如rewrite_by_lua*階段)將資料生成后傳入upstream中,
6、header_filter_by_lua_* 和 body_filter_by_lua_*
使用方法:
header_filter_by_lua_block { lua-script-str } 或
header_filter_by_lua_file filepathbody_filter_by_lua_block { lua-script-str } 或
body_filter_by_lua_file filepath
執行階段分別是:output-header-filter、output-body-filter
header_filter_by_lua_* :對每個請求執行這段 lua 代碼,以此對回應頭進行過濾,常用于對回應頭進行添加、洗掉等操作,用于設定輸出body_filter_by_lua_* :回應體的過濾器,在此階段可以修改回應體的內容,如修改字母的大小寫、替換字串等,
禁用的 lua API :
輸出型別的API函式(如ngx.say和ngx.send_headers),
控制型別的API函式(如ngx.exit),
子請求的API函式(如ngx.location.capture和ngx.location.capture_multi),
Cosocket API函式(如ngx.socket.tcp和ngx.req.socket),
7、log_by_lua_*
使用方法:
log_by_lua_block { lua-script-str } 或
log_by_lua_file filepath
執行階段:log
在日志請求處理階段執行的{ lua-script }代碼,它不會替換當前access請求的日志,而會運行在access的前面,適合用來對日志進行定制化處理,且可以實作日志的集群化維護
禁用的 lua API :
輸出型別的API函式(如ngx.say和ngx.send_headers),
控制型別的API函式(如ngx.exit),
子請求的API函式(如ngx.location.capture和ngx.location.capture_multi),
Cosocket API函式(如ngx.socket.tcp和ngx.req.socket),
休眠API函式ngx.sleep,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/352082.html
標籤:其他
