使用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