基於nginx + lua實現的反向代理動態更新


大家都知道,nginx是當前應用非常廣泛的web服務器,熱度因為他的高並發高性能高可靠性,且輕量級!牛逼的不行,不多說這些。

 

今天要介紹的是,如何基於nginx和lua腳本,也就是在openresty的環境下,實現動態的反向代理邏輯,有一個開關控制。開關控制反向代理工作在nginx原生的upstream的模式,還是工作在lua控制的動態代理模式。 動態代理的服務器,通過http請求實現靈活的操作,向lua_shared_dict定義的全局變量里面寫入或者刪除動態代理的服務器信息。

 

環境信息如下:

1 [root@bogon sbin]# ./nginx -V
2 nginx version: openresty/1.11.2.2
3 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC) 
4 built with OpenSSL 1.0.1e-fips 11 Feb 2013
5 TLS SNI support enabled
6 configure arguments: --prefix=/usr/local/openresty/nginx --with-cc-opt=-O2 --add-module=../ngx_devel_kit-0.3.0 --add-module=../echo-nginx-module-0.60 --add-module=../xss-nginx-module-0.05 --add-module=../ngx_coolkit-0.2rc3 --add-module=../set-misc-nginx-module-0.31 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.06 --add-module=../srcache-nginx-module-0.31 --add-module=../ngx_lua-0.10.7 --add-module=../ngx_lua_upstream-0.06 --add-module=../headers-more-nginx-module-0.32 --add-module=../array-var-nginx-module-0.05 --add-module=../memc-nginx-module-0.17 --add-module=../redis2-nginx-module-0.13 --add-module=../redis-nginx-module-0.3.7 --add-module=../rds-json-nginx-module-0.14 --add-module=../rds-csv-nginx-module-0.07 --with-ld-opt=-Wl,-rpath,/usr/local/openresty/luajit/lib --add-module=/opt/nginx-rtmp-module-master --with-http_ssl_module

 

先設計一下功能模塊,在nginx.conf文件里面,有如下幾個location:

location / {。。。}
業務邏輯的入口

location /config {。。。}
動態反向代理開關控制入口

location /add_ups {。。。}
添加反向代理的服務器信息進入lua_shared_dict定義的全局表單

location /stop_ups {。。。}
從lua_shared_dict定義的全局表單里面刪除掉不再參與反向代理的服務器信息

location /check_ups {。。。}
查看當前lua_shared_dict定義的全局表單里面有那些服務器信息

 

為了驗證這個設計,我在本地開發機器上,將同一個RDConsumer應用部署在3個不同的端口下,對應於nginx里面的upstream塊:

upstream robot_ups {
    server 10.90.9.20:8090;
    server 10.90.9.20:8081;
    server 10.90.9.20:9080;
}

在這里,強調一下,這里,我們驗證的動態反向代理,是輪詢的方式,當然,根據需要可以設計成符合各自業務的邏輯。

 

下面,對這個設計的全部過程進行詳細介紹。若有需要,可以用起來或者轉走,覺得好,還可以點個贊,或者加個關注

 

1. nginx.conf的配置文件

#user  nobody;
worker_processes  4;

error_log  logs/error.log;
error_log  logs/error.log  notice;
error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
    use   epoll;
}

http {
    lua_shared_dict dyn_ups_zone 10m;

    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
 
    upstream robot_ups {
        server 10.90.9.20:8090;
        server 10.90.9.20:8081;
        server 10.90.9.20:9080;
    }

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;
        
        location / {
            set_by_lua_file $cur_ups /opt/shihuc/luahome/ablb/bussups.lua
            proxy_next_upstream off;  
            proxy_set_header Host $host:$server_port;
            proxy_set_header Remote_Addr $remote_addr;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://$cur_ups;  
        } 

        location /config {
            default_type  text/plain;
            content_by_lua_block {
                local foo = ngx.req.get_uri_args()["foo"]
                if foo == nil then
                    ngx.say("usage: /config?foo=off, or /config?foo=on")
                    return;
                end
                ngx.log(ngx.INFO, "config ab deploy feature: ", foo);
                ngx.say("config ab deploy feature: ", foo);
                    
                ngx.shared.dyn_ups_zone:set("robotfoo", foo);
            }
        }

        location /stop_ups {
            default_type  text/plain;
            content_by_lua_file /opt/shihuc/luahome/ablb/stopups.lua;
        }

        location /add_ups {
            default_type  text/plain;
            content_by_lua_block {
                local add_s = ngx.req.get_uri_args()["ups"]  
                if add_s == nil then 
                    ngx.say("usage: /add_ups?ups=x.x.x.x")  
                    return "no add_s"
                end
                ngx.log(ngx.INFO, "add upstream server: ", add_s);
                local dynupszone = ngx.shared.dyn_ups_zone;
                local ups = dynupszone:get("robotups");
                if ups == nil then
                   ngx.say("first init global dict dyn_ups_zone");
                   ups = add_s
                else
                   local unders = "-";
                   ups = ups..unders
                   ups = ups..add_s
                end
                local succ, err, forcible = dynupszone:set("robotups", ups);
                ngx.say("succ: ",succ, ", err: ", err, ", forcible: ", forcible);
                ngx.say(dynupszone.get(dynupszone, "robotups"))
            }
        }
        
        location /check_ups {
            default_type  text/plain;
            content_by_lua_block {
                local dynupszone = ngx.shared.dyn_ups_zone;
                local ups = dynupszone:get("robotups");
                ngx.say(ups);
            }
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}
View Code

 

2. 調用add_ups url向全局緩存lua_shared_dict dyn_ups_zone 10m填寫數據。

對應的后台日志如下:

2017/12/14 18:46:47 [info] 4347#0: *1 [lua] content_by_lua(nginx.conf:133):7: add upstream server: 10.90.9.20:8081, client: 10.90.9.20, server: localhost, request: "GET /add_ups?ups=10.90.9.20:8081 HTTP/1.1", host: "10.90.7.10"
2017/12/14 18:48:35 [info] 4347#0: *3 [lua] content_by_lua(nginx.conf:133):7: add upstream server: 10.90.9.20:8090, client: 10.90.9.20, server: localhost, request: "GET /add_ups?ups=10.90.9.20:8090 HTTP/1.1", host: "10.90.7.10"
2017/12/14 18:49:05 [info] 4347#0: *3 [lua] content_by_lua(nginx.conf:133):7: add upstream server: 10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "GET /add_ups?ups=10.90.9.20:9080 HTTP/1.1", host: "10.90.7.10"

 

3. config配置灰度啟用

日志請參考:

2017/12/14 18:58:05 [info] 4347#0: *7 [lua] content_by_lua(nginx.conf:103):7: config ab deploy feature: on, client: 10.90.9.20, server: localhost, request: "GET /config?foo=on HTTP/1.1", host: "10.90.7.10"

 

4. 在不做灰度停用機器的時候,看看請求如何調度。這里,我的測試應用在本地部署了3個,端口區分。在10.90.7.10這個nginx上做反向代理,輪詢分發請求。我執行了4次請求,通過restlet client (chrome的一個http模擬插件),nginx的后台日志如下:

2017/12/14 19:01:18 [info] 4347#0: *9 [lua] bussups.lua:27: ups: 10.90.9.20:8081-10.90.9.20:8090-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:18 [info] 4347#0: *9 [lua] bussups.lua:28: foo: on, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:18 [info] 4347#0: *9 [lua] bussups.lua:29: cnt: nil, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:18 [info] 4347#0: *9 [lua] bussups.lua:39: ups list: 10.90.9.20:8081-10.90.9.20:8090-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:18 [info] 4347#0: *9 [lua] bussups.lua:50: idx: 3, exc: 3 ,current ups: 10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:19 [info] 4347#0: *9 [lua] bussups.lua:27: ups: 10.90.9.20:8081-10.90.9.20:8090-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:19 [info] 4347#0: *9 [lua] bussups.lua:28: foo: on, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:19 [info] 4347#0: *9 [lua] bussups.lua:29: cnt: 1, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:19 [info] 4347#0: *9 [lua] bussups.lua:39: ups list: 10.90.9.20:8081-10.90.9.20:8090-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:19 [info] 4347#0: *9 [lua] bussups.lua:50: idx: 1, exc: 3 ,current ups: 10.90.9.20:8081, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:21 [info] 4347#0: *9 [lua] bussups.lua:27: ups: 10.90.9.20:8081-10.90.9.20:8090-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:21 [info] 4347#0: *9 [lua] bussups.lua:28: foo: on, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:21 [info] 4347#0: *9 [lua] bussups.lua:29: cnt: 2, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:21 [info] 4347#0: *9 [lua] bussups.lua:39: ups list: 10.90.9.20:8081-10.90.9.20:8090-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:21 [info] 4347#0: *9 [lua] bussups.lua:50: idx: 2, exc: 3 ,current ups: 10.90.9.20:8090, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:22 [info] 4347#0: *9 [lua] bussups.lua:27: ups: 10.90.9.20:8081-10.90.9.20:8090-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:22 [info] 4347#0: *9 [lua] bussups.lua:28: foo: on, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:22 [info] 4347#0: *9 [lua] bussups.lua:29: cnt: 3, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:22 [info] 4347#0: *9 [lua] bussups.lua:39: ups list: 10.90.9.20:8081-10.90.9.20:8090-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:01:22 [info] 4347#0: *9 [lua] bussups.lua:50: idx: 3, exc: 3 ,current ups: 10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"

從日志看,輪詢是沒有問題的。輪詢的依據,是在nginx的全局變量dyn_ups_zone里面定義了一個cnt的變量,記錄請求次數。請求數與當前反向代理里面的機器數量求模。用余數作為lua列表的下標,求出服務器IP端口信息。作為反向代理的機器。
這里要注意的是:
a. lua數組或者列表下標不是從0開始,而是1.
b. lua數組的下標,可以是不同數據類型的值,不像java等高級語言,是數字下標。

 

5. 停用一台服務器,通過stop_ups調用。然后查看反向代理跳轉是否生效。

發現stop操作,有點問題,請看下圖,原來3個應用,停了中間一個,最后的ups列表中怎么只有一個應用服務器信息了?先看看stopups.lua的腳本吧:

#!/usr/bin/env lua

function split(s, delim)
    if type(delim) ~= "string" or string.len(delim) <= 0 then
        return
    end

    local start = 1
    local t = {}
    while true do
        local pos = string.find (s, delim, start, true) -- plain find
        if not pos then
          break
        end

        table.insert (t, string.sub (s, start, pos - 1))
        start = pos + string.len (delim)
    end
    table.insert (t, string.sub (s, start))

    return t
end

local stop_s = ngx.req.get_uri_args()["ups"];
if stop_s == nil then
   ngx.say("usage: /stop_ups?ups=x.x.x.x");
   return "no stop_s"
end
ngx.say("stop upstream server: ", stop_s);
local dynupszone = ngx.shared.dyn_ups_zone;
local ups = dynupszone:get("robotups");
if ups == nil then
   ngx.say("currently, there is no server ip to stop...");
   return;
end
local table_ups = split(ups, "-");
ngx.say(table_ups);
local delid=0;
for k,v in ipairs(table_ups) do
   ngx.say("key: ",k,", value: ", v);
   if v == stop_s then
      delid = k;
   end
end
table_ups[delid] = nil;
ngx.say(table_ups);
local new_ups = table.concat(table_ups,"-");
ngx.say("new ups: ", new_ups);
dynupszone:set("robotups",new_ups);

分析一下,發現,table數據table_ups里面設置nil的值,其實也是可以的。但是,在做table.concat的時候,會將第一個nil作為數據拼接的結束標識了,於是nil后面的數據不被計入。調整一下統計余下應用服務器信息的算法。調整后如下(local table_ups = split(ups, "-");代碼之前的不變):

local table_ups = split(ups, "-");
ngx.say(table_ups);
local new_table_ups = {}
for k,v in ipairs(table_ups) do
   ngx.say("key: ",k,", value: ", v);
   if v ~= stop_s then
      table.insert(new_table_ups, v);
   end
end
ngx.say(new_table_ups);
local new_ups = table.concat(new_table_ups,"-");
ngx.say("new ups: ", new_ups);
dynupszone:set("robotups",new_ups);

重復前面的操作,再進行stop_ups,就得到合理的結果,如圖:

在模擬發送請求4次,看看日志:

2017/12/14 19:18:38 [info] 4747#0: *6 [lua] bussups.lua:27: ups: 10.90.9.20:8081-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:38 [info] 4747#0: *6 [lua] bussups.lua:28: foo: on, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:38 [info] 4747#0: *6 [lua] bussups.lua:29: cnt: nil, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:38 [info] 4747#0: *6 [lua] bussups.lua:39: ups list: 10.90.9.20:8081-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:38 [info] 4747#0: *6 [lua] bussups.lua:50: idx: 2, exc: 2 ,current ups: 10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:39 [info] 4747#0: *6 [lua] bussups.lua:27: ups: 10.90.9.20:8081-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:39 [info] 4747#0: *6 [lua] bussups.lua:28: foo: on, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:39 [info] 4747#0: *6 [lua] bussups.lua:29: cnt: 1, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:39 [info] 4747#0: *6 [lua] bussups.lua:39: ups list: 10.90.9.20:8081-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:39 [info] 4747#0: *6 [lua] bussups.lua:50: idx: 1, exc: 2 ,current ups: 10.90.9.20:8081, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:40 [info] 4747#0: *6 [lua] bussups.lua:27: ups: 10.90.9.20:8081-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:40 [info] 4747#0: *6 [lua] bussups.lua:28: foo: on, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:40 [info] 4747#0: *6 [lua] bussups.lua:29: cnt: 2, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:40 [info] 4747#0: *6 [lua] bussups.lua:39: ups list: 10.90.9.20:8081-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:40 [info] 4747#0: *6 [lua] bussups.lua:50: idx: 2, exc: 2 ,current ups: 10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:40 [info] 4747#0: *6 [lua] bussups.lua:27: ups: 10.90.9.20:8081-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:40 [info] 4747#0: *6 [lua] bussups.lua:28: foo: on, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:40 [info] 4747#0: *6 [lua] bussups.lua:29: cnt: 3, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:40 [info] 4747#0: *6 [lua] bussups.lua:39: ups list: 10.90.9.20:8081-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:18:40 [info] 4747#0: *6 [lua] bussups.lua:50: idx: 1, exc: 2 ,current ups: 10.90.9.20:8081, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"

從日志看,現在ups的服務器只有2個了,剛才stop掉的一個,不再了。執行4次請求,分別在余下的2個服務器之間輪詢。合乎邏輯設計。

 

6. 關閉灰度發布的開發,執行config?foo=off。參考題config_off,nginx的后台日志如下:

2017/12/14 19:21:47 [info] 4747#0: *11 [lua] content_by_lua(nginx.conf:103):7: config ab deploy feature: off, client: 10.90.9.20, server: localhost, request: "GET /config?foo=off HTTP/1.1", host: "10.90.7.10"

 

7. 在關閉灰度開關的情況下,看看反向代理的邏輯。主要看看后台日志:

第1次請求:

2017/12/14 19:23:46 [info] 4747#0: *13 [lua] bussups.lua:27: ups: 10.90.9.20:8081-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:23:46 [info] 4747#0: *13 [lua] bussups.lua:28: foo: off, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:23:46 [info] 4747#0: *13 [lua] bussups.lua:29: cnt: 4, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:23:46 [info] 4747#0: *13 [lua] bussups.lua:56: use default upstream, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"

從部署的3台應用服務器上來看,這次調度到8089端口的應用了。

 

第2次請求:

2017/12/14 19:27:32 [info] 4747#0: *15 [lua] bussups.lua:27: ups: 10.90.9.20:8081-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:27:32 [info] 4747#0: *15 [lua] bussups.lua:28: foo: off, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:27:32 [info] 4747#0: *15 [lua] bussups.lua:29: cnt: 5, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:27:32 [info] 4747#0: *15 [lua] bussups.lua:56: use default upstream, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"

從部署的3台應用服務器上來看,這次調度到8081端口的應用了。

 

第3次請求:

2017/12/14 19:29:31 [info] 4747#0: *17 [lua] bussups.lua:27: ups: 10.90.9.20:8081-10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:29:31 [info] 4747#0: *17 [lua] bussups.lua:28: foo: off, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:29:31 [info] 4747#0: *17 [lua] bussups.lua:29: cnt: 6, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:29:31 [info] 4747#0: *17 [lua] bussups.lua:56: use default upstream, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"

從部署的3台應用服務器上來看,這次調度到9080端口的應用了。

 

基於上面3次foo=off的模擬調用來看,程序運行於upstream模塊的輪詢模式。這個時候全局變量ups里面只有2個服務器應用。

 

8. 將剛才灰度停用的服務器8090加回來,再次啟用foo=on,動態輪詢驗證。

2017/12/14 19:32:19 [info] 4747#0: *19 [lua] content_by_lua(nginx.conf:133):7: add upstream server: 10.90.9.20:8090, client: 10.90.9.20, server: localhost, request: "GET /add_ups?ups=10.90.9.20:8090 HTTP/1.1", host: "10.90.7.10"
2017/12/14 19:34:01 [info] 4747#0: *23 [lua] content_by_lua(nginx.conf:103):7: config ab deploy feature: on, client: 10.90.9.20, server: localhost, request: "GET /config?foo=on HTTP/1.1", host: "10.90.7.10"

2017/12/14 19:34:20 [info] 4747#0: *23 [lua] bussups.lua:27: ups: 10.90.9.20:8081-10.90.9.20:9080-10.90.9.20:8090, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:20 [info] 4747#0: *23 [lua] bussups.lua:28: foo: on, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:20 [info] 4747#0: *23 [lua] bussups.lua:29: cnt: 7, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:20 [info] 4747#0: *23 [lua] bussups.lua:39: ups list: 10.90.9.20:8081-10.90.9.20:9080-10.90.9.20:8090, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:20 [info] 4747#0: *23 [lua] bussups.lua:50: idx: 1, exc: 3 ,current ups: 10.90.9.20:8081, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:20 [info] 4747#0: *23 [lua] bussups.lua:27: ups: 10.90.9.20:8081-10.90.9.20:9080-10.90.9.20:8090, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:20 [info] 4747#0: *23 [lua] bussups.lua:28: foo: on, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:20 [info] 4747#0: *23 [lua] bussups.lua:29: cnt: 8, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:20 [info] 4747#0: *23 [lua] bussups.lua:39: ups list: 10.90.9.20:8081-10.90.9.20:9080-10.90.9.20:8090, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:20 [info] 4747#0: *23 [lua] bussups.lua:50: idx: 2, exc: 3 ,current ups: 10.90.9.20:9080, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:21 [info] 4747#0: *23 [lua] bussups.lua:27: ups: 10.90.9.20:8081-10.90.9.20:9080-10.90.9.20:8090, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:21 [info] 4747#0: *23 [lua] bussups.lua:28: foo: on, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:21 [info] 4747#0: *23 [lua] bussups.lua:29: cnt: 9, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:21 [info] 4747#0: *23 [lua] bussups.lua:39: ups list: 10.90.9.20:8081-10.90.9.20:9080-10.90.9.20:8090, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:21 [info] 4747#0: *23 [lua] bussups.lua:50: idx: 3, exc: 3 ,current ups: 10.90.9.20:8090, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:22 [info] 4747#0: *23 [lua] bussups.lua:27: ups: 10.90.9.20:8081-10.90.9.20:9080-10.90.9.20:8090, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:22 [info] 4747#0: *23 [lua] bussups.lua:28: foo: on, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:22 [info] 4747#0: *23 [lua] bussups.lua:29: cnt: 10, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:22 [info] 4747#0: *23 [lua] bussups.lua:39: ups list: 10.90.9.20:8081-10.90.9.20:9080-10.90.9.20:8090, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10" 2017/12/14 19:34:22 [info] 4747#0: *23 [lua] bussups.lua:50: idx: 1, exc: 3 ,current ups: 10.90.9.20:8081, client: 10.90.9.20, server: localhost, request: "POST /RDConsumer/httpclient/conrst HTTP/1.1", host: "10.90.7.10"

從nginx日志以及應用程序的后台日志看,灰度的負載均衡方向代理邏輯,依然正常。

 

到此,整個驗證完美收官!下面,附上,nginx.conf配置中涉及到的幾個lua的腳本文件:

bussups.lua:

#!/usr/bin/env lua

function split(s, delim)
    if type(delim) ~= "string" or string.len(delim) <= 0 then
        return
    end

    local start = 1
    local t = {}
    while true do
        local pos = string.find (s, delim, start, true) -- plain find
        if not pos then
          break
        end

        table.insert (t, string.sub (s, start, pos - 1))
        start = pos + string.len (delim)
    end
    table.insert (t, string.sub (s, start))

    return t
end

local ups = ngx.shared.dyn_ups_zone:get("robotups");
local foo = ngx.shared.dyn_ups_zone:get("robotfoo");
local cnt = ngx.shared.dyn_ups_zone:get("robotcnt");
ngx.log(ngx.INFO, "ups: ", ups);
ngx.log(ngx.INFO, "foo: ", foo);
ngx.log(ngx.INFO, "cnt: ", cnt);

if cnt == nil then
   cnt = 0;
end
ngx.shared.dyn_ups_zone:set("robotcnt", cnt+1);

if foo == "on" then
   if ups ~= nil then
      --ngx.log(ngx.info, "get robotups server list: ", ups)
      ngx.log(ngx.INFO, "ups list: ", ups);
      local table_ups = split(ups, "-");
      local exc = 0;
      for k,v in ipairs(table_ups) do
          exc = exc + 1;
      end
      local idx = cnt % exc;
      if idx == 0 then  --lua array index from 1, not from 0
         idx = exc;
      end
      local cur_ups = table_ups[idx];
      ngx.log(ngx.INFO, "idx: ", idx, ", exc: ", exc,  " ,current ups: ", cur_ups);
      return cur_ups
   end
   ngx.log(ngx.INFO, "ab lb configuration error, use default upstream");
   return "robot_ups";
else
   ngx.log(ngx.INFO, "use default upstream");
   return "robot_ups";
end

 

stopups.lua:

#!/usr/bin/env lua

function split(s, delim)
    if type(delim) ~= "string" or string.len(delim) <= 0 then
        return
    end

    local start = 1
    local t = {}
    while true do
        local pos = string.find (s, delim, start, true) -- plain find
        if not pos then
          break
        end

        table.insert (t, string.sub (s, start, pos - 1))
        start = pos + string.len (delim)
    end
    table.insert (t, string.sub (s, start))

    return t
end

local stop_s = ngx.req.get_uri_args()["ups"];
if stop_s == nil then
   ngx.say("usage: /stop_ups?ups=x.x.x.x");
   return "no stop_s"
end
ngx.say("stop upstream server: ", stop_s);
local dynupszone = ngx.shared.dyn_ups_zone;
local ups = dynupszone:get("robotups");
if ups == nil then 
   ngx.say("currently, there is no server ip to stop...");
   return;
end
local table_ups = split(ups, "-");
ngx.say(table_ups);
local new_table_ups = {}
for k,v in ipairs(table_ups) do
   ngx.say("key: ",k,", value: ", v);
   if v ~= stop_s then
      table.insert(new_table_ups, v);
   end
end
ngx.say(new_table_ups);
local new_ups = table.concat(new_table_ups,"-");
ngx.say("new ups: ", new_ups);
dynupszone:set("robotups",new_ups);

 

nginx功能強大,配合上lua腳本,在ngx_lua模塊的存在下,功能就更加強大。感興趣的話,可以加我關注喲,我們一起探討!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM