前言
項目需要在登錄之前調用登陸調度接口來獲取登錄接口的IP地址,如此便需要Nginx在登陸調度接口之后動態的對登錄接口的IP地址進行賦值,因此決定在服務器安裝OpenResty,利用Redis緩存功能、Lua的代碼編寫功能對Nginx的配置文件進行修改。
下載
從下載頁 Download下載最新的 OpenResty® 源碼包
wget https://openresty.org/download/openresty-1.19.9.1.tar.gz
安裝前的准備
安裝依賴庫 perl 5.6.1+, libpcre, libssl
yum install pcre-devel openssl-devel gcc curl -y
安裝
tar -zxvf openresty-1.19.9.1.tar.gz
cd openresty-1.19.9.1
./configure
make
make install
如果支持多核 make 工作的特性, 可以這樣編譯:
make -j2
默認, --prefix=/usr/local/openresty 程序會被安裝到/usr/local/openresty目錄。
也可以指定各種選項:
./configure --prefix=/opt/openresty \
--with-luajit \
--with-http_redis2_module
使用 ./configure --help 可以查看更多的選項。
配置
修改Nginx配置文件nginx.conf
server {
server_name 域名;
listen 服務器端口 ssl;
ssl_certificate /opt/openresty/nginx/cert/FullSSL.crt;
ssl_certificate_key /opt/openresty/nginx/cert/SSL.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
location /{
root /opt/openresty/nginx/html;
}
# 登陸調度
location /LoginRoute {
proxy_pass https://IP:port/***/**;
}
# 保存URL
location = /SaveUrl {
internal;
set_unescape_uri $key $arg_key;
set_unescape_uri $value $arg_value;
redis2_query set $key $value;
redis2_pass 127.0.0.1:6379;
}
# 入口
location = /Entrance{
content_by_lua_block {
local cjson = require "cjson"
ngx.req.read_body()
-- 解析前端請求,獲取其中userId
local bodyData = ngx.req.get_body_data();
local data = cjson.decode(bodyData);
local userId = data["userId"];
ngx.log(ngx.ERR, "useridis : ", userId)
-- 發起登錄調度請求
local res = ngx.location.capture("/LoginRoute", { method = ngx.HTTP_POST, body = bodyData})
if res.status == 200 then
local resData = cjson.decode(res.body);
-- 請求成功,獲取serviceUrl,並保存redis
local serviceUrl = string.gsub(resData["vspURL"], "http://", "");
ngx.log(ngx.ERR, "serviceUrl ====== : ", serviceUrl);
local saveRes = ngx.location.capture(
"/SaveUrl", { args = { key = userId, value = serviceUrl} })
end
-- 返回請求結果
ngx.say(res.body)
ngx.exit(res.status)
}
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_set_header Cookie $http_cookie;
}
# 獲取URL
location = /getUrl {
internal;
set_unescape_uri $key $arg_key;
redis2_query get $key;
redis2_pass 127.0.0.1:6379;
}
# 更改接口的URL
location /Interface {
set $target '';
access_by_lua '
local key = ngx.req.get_headers().userId
-- 從Redis獲取該用戶的Url
local res = ngx.location.capture(
"/getUrl", { args = { key = key } }
)
if res.status ~= 200 then
ngx.log(ngx.ERR, "redis server returned bad status: ",
res.status)
ngx.exit(res.status)
end
if not res.body then
ngx.log(ngx.ERR, "redis returned empty body")
ngx.exit(500)
end
-- 從Redis解析出該用戶的Url
local parser = require "redis.parser"
local server, typ = parser.parse_reply(res.body)
if typ ~= parser.BULK_REPLY or not server then
ngx.log(ngx.ERR, "bad redis response: ", res.body)
ngx.exit(500)
end
-- 設置重定向的url
ngx.var.target = server
ngx.log(ngx.ERR, "server is =========: ",server)
';
proxy_pass http://$target;
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_set_header X_CSRFToken $csrftoken;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
實現
在前端代碼中先調用/Entrance,並在請求參數中添加key為userId的參數,Nginx會使用Redis將userId和URL做為鍵值對存儲起來。后續的接口調用中,在參數列表里都加入前面的userId參數,Nginx會通過這個參數取到所需的URL。