使用OpenResty、Redis、Lua动态改变Nginx转发地址


前言

项目需要在登录之前调用登陆调度接口来获取登录接口的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。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM