美文网首页Linux系统应用
灰度发布-Openresty+lua实现动态upstream

灰度发布-Openresty+lua实现动态upstream

作者: 老夫刘某 | 来源:发表于2017-11-07 14:51 被阅读806次

    动态的负载均衡控制;
    平滑上下线服务,升级服务;
    高可能保证–自动踢离线服务下线;
    具体思路
    利用lua中 "lua_shared_dict" 指令开辟一个共享内存空间;
    通过API动态根据key值&参数修改 upstream (这里使用 host 作为key);
    利用 proxy_pass 可使用变量特性及lua指令 "set_by_lua" 动态修改当前 upstream 变量即可;
    配置:

    worker_processes  1;
    pid        logs/nginx.pid;
    events {
        worker_connections  1024;
    }
     
    http {
        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"';
        sendfile        on;
     
        keepalive_timeout  65;
              
        #lua_shared_dict upstreams 1m;  # 声明一个ngx多进程全局共享内存区域,_G 作为基于shm的Lua字典的存储空间ngx.shared.<name>   
        lua_shared_dict _ups_zone 64m; # 定义upstream共享内存空间
     
     
            
        upstream backend {                        # 配置后端服务器组
                    server 127.0.0.1:18084;
                    server 127.0.0.1:18083;
        }
     
        server {
            listen       8000;
            server_name  localhost;
     
            access_log  logs/80.access.log  main;
            error_log   logs/80.error.log error;
     
     
    #更新API接口
            location = /ups_update {  
                content_by_lua '  
                    local ups = ngx.req.get_uri_args()["ups"]  
                    if ups == nil then 
                        ngx.say("usage: /ups_update?ups=x.x.x.x")  
                        return 
                    end  
                    local host = ngx.var.http_host  
                    local ups_from = ngx.shared._ups_zone:get(host);  
                    ngx.log(ngx.WARN, host, " update upstream from ", ups_from, " to ", ups)  
                    ngx.shared._ups_zone:set(host, ups);  
                    ngx.say(host, " update upstream from ", ups_from, " to ", ups)  
                ';  
            }
     
    location / {  
                # 动态设置当前 upstream, 未设置则使用默认 upstream  
                set_by_lua $cur_ups '  
                    local ups = ngx.shared._ups_zone:get(ngx.var.http_host)  
                    if ups ~= nil then 
                        ngx.log(ngx.ERR, "get [", ups, "] from ngx.shared._ups_zone")  
                        return ups  
                    end  
                    --ngx.log(ngx.INFO, "use default upstream");  
                    return "qq_backend";  
                '  
                proxy_next_upstream off;  
                proxy_set_header    Host $host;  
                proxy_http_version  1.1;  
                proxy_set_header    Connection  "";  
                proxy_pass $scheme://$cur_ups;  
            }
     
     
    }
     
    
    }
    

    测试切换upstream的backend效果:
    1、默认情况【请求4次】:

    root@ubuntu:~# curl  127.0.0.1:8000
    83 server
    root@ubuntu:~# curl  127.0.0.1:8000
    84 server 
    root@ubuntu:~# curl  127.0.0.1:8000
    83 server
    root@ubuntu:~# curl  127.0.0.1:8000
    84 server 
    

    切换upstream

    root@ubuntu:~# curl  127.0.0.1:8000/ups_update?ups=127.0.0.1:18083
    127.0.0.1:8000 update upstream from 127.0.0.1:18083 to 127.0.0.1:18083
    root@ubuntu:~# curl  127.0.0.1:8000
    83 server
    root@ubuntu:~# curl  127.0.0.1:8000
    83 server
    root@ubuntu:~# curl  127.0.0.1:8000
    83 server
    root@ubuntu:~# curl  127.0.0.1:8000
    83 server
    

    切换upstream:

    worker_processes  1;
    pid        logs/nginx.pid;
    events {
        worker_connections  1024;
    }
     
    http {
        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"';
        sendfile        on;
     
        keepalive_timeout  65;
              
        lua_shared_dict upstreams 1m;  # 声明一个ngx多进程全局共享内存区域,_G 作为基于shm的Lua字典的存储空间ngx.shared.<name>   
        upstream default_upstream {                        # 配置后端服务器组
                    server 127.0.0.1:18081;
                    server 127.0.0.1:18082;
        }
             
        upstream lua_upstream {                        # 配置后端服务器组
                    server 127.0.0.1:18084;
                    server 127.0.0.1:18083;
        }
     
        server {
            listen       8000;
            server_name  localhost;
     
            access_log  logs/80.access.log  main;
            error_log   logs/80.error.log error;
     
            location = /_switch_upstream {
                 content_by_lua_block{
                        local ups = ngx.req.get_uri_args()["upstream"]
                        if ups == nil or ups == "" then
                            ngx.say("upstream is nil 1")
                            return nil
                        end
                        local host = ngx.var.http_host
                        local upstreams = ngx.shared.upstreams
                        local ups_src = upstreams:get(host)
                        ngx.say("Current upstream is :",ups_src)
                        ngx.log(ngx.WARN, host, " change upstream from ", ups_src, " to ", ups)
                        local succ, err, forcible = upstreams:set(host,  ups)
                        ngx.say(host, " change upstream from ", ups_src, " to ", ups)
                }
            }
             
            location / {
                set_by_lua_block $my_upstream {
                    local ups = ngx.shared.upstreams:get(ngx.var.http_host)
                    if ups ~= nil then
                        ngx.log(ngx.ERR, "get [", ups,"] from ngx.shared")
                        return ups
                    end
                    return "default_upstream"
                }
     
                proxy_next_upstream off;
                proxy_set_header    X-Real-IP           $remote_addr;
                proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
                proxy_set_header    Host                $host;
                proxy_http_version  1.1;
                proxy_set_header    Connection  "";
                proxy_pass          http://$my_upstream ;
            }
        }   
     
       
    }
    

    切换:

    curl 127.0.0.1:8000/_switch_upstream?upstream=lua_upstream
    curl 127.0.0.1:8000/_switch_upstream?upstream=default_upstream
    

    这里用的还是静态文件,改成tomcat服务之后也是可以进行代理的切换。要是想持久化的话 ,得用到redis。

    相关文章

      网友评论

        本文标题:灰度发布-Openresty+lua实现动态upstream

        本文链接:https://www.haomeiwen.com/subject/nakjmxtx.html