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