由於獨立秒殺目前接過來了,但是其核心是利用openresty實現的,本人對此技術棧較爲陌生,特寫下本篇指導,以期快速上手。
一、openresty入門初步
安裝openresty
首先是安裝openresty,macOS的安裝方式
brew tap openresty/brew
brew install openresty
安裝完畢之後,可以得到安裝路徑,配置到系統PATH中並生效:
export PATH=/usr/local/Cellar/openresty/1.21.4.1_2/nginx/sbin:$PATH
之後就可以校驗是否安裝成功了,按照如下命令檢測:
which nginx
結果顯示如下的路徑:/usr/local/Cellar/openresty/1.21.4.1_2/nginx/sbin/nginx,則證明安裝成功;如果沒有任何輸出,則表明未安裝成功,可以檢查安裝路徑是否正確。
初步使用
新建個文件夾,然後利用如下命令新建conf,logs兩個字文件夾:
mkdir conf logs
之後,進行nginx配置文件配置,運行命令如下:
nano conf/nginx.conf
輸入內容如下:
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
server {
listen 8080;
location / {
default_type text/html;
content_by_lua_block {
ngx.say("<p>hello, world</p>")
}
}
}
}
寫完之後,可以測試腳本是否正常:
openresty -p $PWD/ -c conf/nginx.conf -t
之後在當前目錄啓動即可:
openresty -p $PWD/ -c conf/nginx.conf
利用如下命令可以看到啓動的master,worker進程
ps aux|grep nginx|grep -v /tmp/
這裏需要注意下,一些常用的openresty命令如下
(1) 啓動 openresty
(2) 重啓 openresty -s reload
(3) 關閉 openresty -s stop
瀏覽器中輸入 http://127.0.0.1:8080就可以看到正常的輸出結果了。
二、簡單的lua腳本
創建新的文件夾,名稱分別爲 log,conf, lua,命令如下:
mkdir logs conf lua
nginx.conf文件內容如下:
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
server {
listen 8080;
location / {
default_type text/html;
content_by_lua_file /Users/shichaoyang/openresty/hello-module/lua/hello.lua;
}
}
}
可以看到,這裏利用content_by_lua_file命令來制定lua腳本文件。其中hello.lua的內容爲 :
ngx.say("hello lua");
之後在當前目錄啓動即可:
openresty -p $PWD/ -c conf/nginx.conf
在瀏覽器訪問,即可以看到正確的輸出結果了。
三、lua腳本模塊
同樣創建logs,conf,lua文件夾,其中nginx.conf文件內容如下:
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
lua_package_path "/usr/local/Cellar/openresty/1.21.4.1_2/?.lua;;$prefix/lua/?.lua;";
server {
listen 8081 reuseport;
location / {
default_type text/plain;
content_by_lua_block {
local hello = require "mod"
hello.greet("a lua module");
}
}
}
}
腳本內容如下:
local _M = {}
function _M.greet(name)
ngx.say("hello from name ",name)
end
return _M
之後在當前目錄啓動即可:
openresty -p $PWD/ -c conf/nginx.conf
可以看到,腳本模塊的封裝方式。這裏需要說明下,nginx啓動的時候會從lua_package_path指定的路徑中將lua文件加載進來。而content_by_lua_block則可以指定執行的業務邏輯代碼。
這裏也許有人要問,爲什麼把openresty按住根目錄下的lua文件都加載進來呢,主要原因是因爲模塊的執行需要resty.core的支持,如果不加入usr/local/Cellar/openresty/1.21.4.1_2/?.lua;; 報錯:
ginx: [alert] failed to load the 'resty.core' module (https://github.com/openresty/lua-resty-core); ensure you are using an OpenResty release from https://openresty.org/en/download.html (reason: module 'resty.core' not found:
no field package.preload['resty.core']
所以這裏需要將lua_package_path改成 lua_package_path "$prefix/lua/?.lua;/usr/local/lib/lua/?.lua;;";
參見:https://github.com/openresty/lua-nginx-module/issues/1533
四、lua腳本傳參
本指導來源於chatGPT回答:
我:openresty多模塊之間傳參,寫一個在兩個網頁中傳參的代碼示例
ChatGPT:
以下是一個在兩個頁面之間傳參的OpenResty代碼示例:
location /page1 {
content_by_lua_block {
local param1 = ngx.var.arg_param1
local param2 = ngx.var.arg_param2
ngx.redirect("/page2?param1=" .. param1 .. "& param2=" .. param2)
}
}
location /page2 {
content_by_lua_block {
local param1 = ngx.var.arg_param1
local param2 = ngx.var.arg_param2
-- Do something with the two parameters here
}
}
這裏我們就根據其指導來實現一下。
同樣的,創建logs,conf,lua文件夾,然後nginx.conf內容如下:
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
server {
listen 8080;
location /p1 {
default_type text/html;
content_by_lua_file /Users/shichaoyang/openresty/trans-module/lua/p1.lua;
}
location /p2 {
default_type text/html;
content_by_lua_file /Users/shichaoyang/openresty/trans-module/lua/p2.lua;
}
}
}
lua腳本p1內容如下:
local param1 = ngx.var.arg_param1
local param2 = ngx.var.arg_param2
ngx.redirect("/p2?param1=" .. param1 .. "& param2=" .. param2)
lua腳本p2內容如下:
local param1 = ngx.var.arg_param1
local param2 = ngx.var.arg_param2
ngx.say(param1)
ngx.say(param2)
之後在當前目錄啓動即可:
openresty -p $PWD/ -c conf/nginx.conf
之後訪問:
http://127.0.0.1:8080/p1?param1=1& param2=2
則會自動跳轉到
http://127.0.0.1:8080/p2?param1=1& param2=2
並輸出1 2
更多內容請訪問:https://openresty-reference.readthedocs.io/en/latest/Lua_Nginx_API/
五、lua腳本調試
同樣的,創建logs,conf,lua文件夾,然後nginx.conf內容如下:
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
lua_package_path "/usr/local/Cellar/openresty/1.21.4.1_2/?.lua;;$prefix/lua/?.lua;";
server {
listen 8080;
location / {
default_type text/html;
content_by_lua_file /Users/shichaoyang/openresty/ut-module/lua/ut.lua;
}
location /test {
content_by_lua_file /Users/shichaoyang/openresty/ut-module/lua/uttest.lua;
}
}
}
ut.lua腳本內容如下:
ngx.say("111")
uttest.lua腳本內容如下:
local iresty_test = require "iresty_test"
local tb = iresty_test.new({unit_name="example"})
function tb:init( )
self:log("init complete")
end
function tb:test_00001( )
error("invalid input")
end
function tb:atest_00002()
self:log("never be called")
end
function tb:test_00003( )
self:log("ok")
end
-- units test
tb:run()
這裏需要從https://github.com/iresty/lua-resty-test/blob/master/lib/resty/iresty_test.lua將此文件下載,並放到lua文件夾下面
之後在當前目錄啓動即可:
openresty -p $PWD/ -c conf/nginx.conf
訪問:http://127.0.0.1:8080/test 即可得到測試結果:
0.000 [32m[example] [m[32munit test start
[m0.000 [32m[example] [minit complete
0.000 [32m \_[test_00001] [m[33mfail /Users/shichaoyang/openresty/ut-module/lua/uttest.lua:9: invalid input
[m0.000 [32m \_[test_00003] [m鈫搊k
0.000 [32m \_[test_00003] [m[32mPASS
[m0.000 [32m[example] [m[32munit test complete
[m
六、openresty配置必知必會
1. proxy_pass, 反向代理,是指以代理服務器接收Internet上的鏈接請求,然後將請求轉發給內部網絡上的服務器,並將從服務器上得到的結果返回給Internet上請求連接的客戶端。
舉個例子,比如我的內部服務器是放在212環境上,那麼開發的接口如下這樣的:
http://192.168.1.212:8136/xxxx 然後端口號是8136,然後直接訪問該接口會返回對應的數據,但是接口一般都是域名訪問的,因此我們需要在nginx上配置一個域名,假如爲 xy.xxx.com, 然後當我們在聯調接口的時候,我們使用 http://xy.xxx.com/xxxx 這樣的接口時,它會反向代理到 http://192.168.1.212:8136/xxxx 上來,這樣它會返回內部服務器的數據給客戶端,客戶端就拿到對應的數據顯示出來了。
2. resolver , DNS解析,一般配製成公共的或者公司內部的都行。
3. allow & deny, allow 和 deny 指令在 ngx_http_access_module 模塊中,兩個指令分別表示允許或禁止源 IP 訪問,用於對源 IP 做訪問控制,nginx 是按照自上而下的順序進行匹配,匹配到一個就不往下繼續了。
allow 指令
a、允許哪些 IP 訪問,all 表示允許所有;
b、作用域 http / server / location / limit_except ;
deny 指令
a、禁止哪些 IP 訪問,all 表示禁止所有;
b、作用域 http / server / location / limit_except ;
location = /request_stat {
allow 192.168.0.0/16;
deny all;
request_status on;
}
4. stub_status, stub_status模塊參數可以用來查看Nginx的一些狀態信息如連接數、請求數統計等,需要安裝好相應的模塊stub_status才支持配置,安裝時需要指定–with-http_stub_status_module。參考: https://blog.csdn.net/jxlhljh/article/details/126270472
location = /status {
allow 192.168.0.0/16;
deny all;
stub_status on;
access_log off;
}
5. access_log, 日誌文件一般存放在 /var/log/nginx 下,若是docker啓動則可以使用主機掛載位置,直接使用 tail -f命令即可查看access日誌。參考: https://blog.csdn.net/weixin_45698637/article/details/128486012
6. set指令, set 指令是用於定義一個變量,並且賦值。這些變量值可以通過ngx.arg.xxx在lua文件內部使用。
#black list redis
set $risk_control_server "127.0.0.1";
set $risk_control_port 6380;
7. log_by_lua, log_by_lua* 是一個請求經歷的最後階段。由於記日誌跟應答內容無關,Nginx 通常在結束請求之後才更新訪問日誌。由此可見,如果我們有日誌輸出的情況,最好統一到 log_by_lua* 階段。如果我們把記日誌的操作放在 content_by_lua* 階段,那麼將線性的增加請求處理時間。 api文檔參考: https://www.kancloud.cn/qq13867685/openresty-api-cn/159199
8. localtion @, 命名location,用@標識,類似於定於goto語句塊。
location @item_fail {
default_type application/json;
content_by_lua_file /export/runtime/WEB-INF/classes/new_lua/item_fail.lua;
}
error_page 404 @item_fail;
error_page 500 502 503 504 @item_fail;
9. limit_req & limit_req_zone, 限流,基於漏桶算法實現的。
limit_req_zone $binary_remote_addr zone=perip_rps:10m rate=5r/s; #單ip每秒限制5個請求
limit_req_zone $server_name zone=perserver_rps:10m rate=3000r/s; #每個server每秒限制處理3000個請求
上面分別是按照ip和server來限流rps,zone=perip_rps:10m是設定這個limit_req_zone的名字爲perid_rps,且在nginx內存裏分配10m的空間來存儲訪問頻次信息,rate=15r/s表示每秒15個請求,30r/m每分鐘30次請求。
一般在http裏配置好了limit_req_zone之後,就可以在server或者location裏邊配置limit_req了,比如:
limit_req zone=perserver_rps burst=2000 nodelay; #server每秒請求限流
limit_req zone=perip_rps burst=10 nodelay; #每個ip每秒請求如果超過limit_req_zone的配置,最多可以緩衝10個
這裏設置 brust=10,表示在超過限制速率 5r/s 的時候,同時至多允許額外有 10 個請求排隊等候,待平均速率迴歸正常後,隊列前面的請求會優先被處理。
參考: http://events.jianshu.io/p/9db107f579a5
參考: https://www.upyun.com/opentalk/opentalk/417.html
參考: https://www.w3cschool.cn/openresty1/