1. 程式人生 > >nginx+lua實現post請求引數提取為一致性雜湊引數

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;  
  }
}