nginx+lua實現post請求引數提取為一致性雜湊引數
nginx的ip_hash,要求nginx一定是最前端伺服器,否則nginx得不到正確的ip值。若nginx不是最前端伺服器,且沒有實現session共享機制,使用ip_hash演算法,會導致nginx使用的ip不是客戶端ip,達不到預期效果。假定每個訪問的客戶端都會攜帶固定引數,如身份證號。可選用“一致性雜湊演算法”,對身份證進行hash計算,將請求分配到相應節點,從而降低所有使用者請求分配到一個節點的風險。
nginx提供的配置引數,提供了取GET請求引數的配置(arg_引數名),但是從提供的引數中,POST請求引數,沒有提供相應的配置,因此,需要結合nginx外掛,提取POST請求引數及其值。
假定nginx已正確安裝,若未安裝nginx,請先安裝再進行如下步驟。
lua安裝
安裝外掛:luajit-2.0.5.tar.gz(推薦最新2.1)、lua-nginx-module-master.zip、ngx_devel_kit-master.zip、lua-cjson-2.1.0.tar.gz(字串格式化成json物件)。
上述外掛,上傳至/usr/local/src目錄
1、 luajit安裝
tar -xvf luajit-2.0.5.tar.gz
cd luajit-2.0.5
make PREFIX=/usr/local/luajit
make install PREFIX=/usr/local/luajit
2、 lua-nginx-module-master.zip安裝
解壓到/usr/local/src目錄即可
3、 ngx_dev_kit-master安裝
解壓值/usr/local/src即可
4、 設定環境變數
vi /ect/profile,新增如下配置,路徑值以實際為準,可到/usr/local/luajit下檢視
export LD_LIBRARY_PATH=/usr/local/luajit/lib;$LD_LIBRARY_PATH
export LUAJIT_LIB=/usr/locall/luajit/lib
export LUAJIT_INC=/usr/local/luajit/include/luajit-2.0
使修改生效: source /ect/profile
5、 nginx 重新設定
進入nginx解壓目錄
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-pcre=/tmp/pcre-8.3.8 --with-threads --with-file-aio --with-http_realip_module --add-module=/usr/local/src/lua-nginx-module-master --add-module=/usr/local/src/ngx_devel_kit-master
make
make install
驗證是否成功安裝
/usr/local/nginx/sbin/nginx -v
啟動nginx
/usr/local/nginx/sbin/nginx
6、 cjson安裝(json格式化post請求引數)
修改Makefile檔案的LUA_INCLUDE_DIR變數為如下值(先確認luajit安裝路徑/usr/local/luajit/include/luajit-2.0)
LUA_INCLUDE_DIR=/usr/local/luajit/include/luajit-2.0
安裝步驟如下
tar -xvf lua-cjson-2.1.0.tar.gz
cd lua-cjson-2.1.0
make
驗證是否安裝正確
#lua
>local gcjson=require("cjson")
>
無錯誤輸出,正確。
重啟nginx
nginx -s stop
nginx -s reload
7、 nginx.conf配置檔案說明
nginx的配置檔案nginx.conf,需新增配置如下
1. log_format定義日誌格式,
2. 一致性hash指令:hash $id consistent
3. GET請求,不做特殊處理,利用nginx預設配置arg_paramName取值。
4. POST請求,使用rewrite_by_lua程式碼塊,獲取POST請求引數,ngx.req.get_post_args()取不到引數值,用ngx.req.get_body_data(),能取到引數值,但為string型別,需要用cjson轉換成json格式,再取引數值。
5. 在rewrite_by_lua內,對變數id的操作,需在變數前加ngx.var. 如ngx.var.id
···
http{
log_format main 'id=[$id]'; #列印身份證號的格式
upstream /hello{
hash $id consistent; #一致性hash
server 192.168.1.1;
server 192.168.1.2;
}
server{
listen 8888;
server 192.168.10.10;
set $id '1'; #設定id預設值1
location /test{
if ($request_method = "GET"){
set $id $arg_id;
}
if ($request_method = "POST"){
rewrite_by_lua '
local gcjson=require("cjson")
ngx.req.read_body()
local args=ngx.req.get_body_data()
local arg=gcjson.decode(args)
ngx.var.id=arg["id"]
';
}
proxy_pass http://hello;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
}
access_log logs/lbroute.log main;
}
}