Openresty+Redis 动态切换upstream

场景
当版本切换的时候,后端服务器不可能瞬间同时进行代码更新,这样就会出现客户在短暂时间内访问到不一样版本的服务。前端

使用如下流程能够避免上述问题:
1.后端设立两个的主机组(A_CLUSTER,B_CLUSTER),以及一个ALL_CLUSTER包含两个主机组提供服务。
2.当要发布前,将全部的流量切换到B_CLUSTER。
3.切换完毕后升级A_CLUSTER代码。
4.将流量再切换到A_CLUSTER。
5.再升级B_CLUSTER的代码。
6.最后将流量再切换至两CLUSTER。nginx

要完成上述操做,在代码更新方面有jenkins等发布工具来实现。但前端切换流量的在传统中只能经过手动修改nginx配置文件来实现。redis

openresty提供了一个可编程的nginx,经过lua能够实现对于nginx的”在线修改”,从redis获取信息从而选择将请求发送到后端指定的upsteam。而如何指定所须要的upstream?这时就须要redis,或者其余的中间件或其余lua能够调用的接口来实现。编程

准备工做
1.安装redis
2.安装openrestry
3.安装lua
4,安装lua的redis驱动后端

配置分享
nginx.conf:服务器

http {
    lua_shared_dict vtimes 10m;
    upstream a_cluster {
        server 192.168.1.200:8888;
    }
    upstream b_cluster {
        server 192.168.1.203:8080;
    }

    init_by_lua_block {
        cache = ngx.shared.vtimes
                cache:set("times",1000)
        redis = require "redis"
                client = redis.connect('127.0.0.1', 6379)
                local cluster = client:get("usCluster");
                cache:set("cluster",cluster);
        }
    server {
        listen 8080;
    location ~ /vtimes/ {
        content_by_lua_block{
            cache = ngx.shared.vtimes;
            times = cache:get("times");
            ngx.say(times);
        }
    }
    location  / {
        set_by_lua_block $upstream{
            cache = ngx.shared.vtimes;
            vtimes = cache:get("times");
            if(vtimes > 0)then
                cluster = cache:get("cluster");
                vtimes = vtimes - 1;
                cache:set("times",vtimes);
                return cluster;
            else
                redis = require "redis"
                client = redis.connect('127.0.0.1', 6379)
                local cluster = client:get("usCluster");
                cache:set("times",1000);
                cache:set("cluster",cluster)
                return cluster;
            end
        }
        proxy_pass http://$upstream;
    }
    }

配置说明
1.若是每次访问都须要访问redis,这将致使效率降低。运维

2.基于第一条缘由,咱们设定这样一个机制,每1000次(这个数值能够本身设定),从redis中获取指定的upstream数值,而后保存在内存中,并使用这个设定。ide

3.这样除了须要在redis中保存数据,还须要在openrestry中保存当前upstream以及访问次数的数据。工具

4.lua_shared_dict vtimes 10m;开辟了一个共享内存空间,能够将数据以key-value形式保存到内存内。ui

5.创建两个upstream,这里做为演示就作的比较简单,事实上能够作无数多个,用于指定。

6.init_by_lua_block;用于初始化数据,在程序启动前,就从redis中获取设定的访问upstream,以及设定访问次数。

7./vtimes/;用于查看访问次数,当次数到达0以后,openresty将从新获取配置。固然也能够配置一个用于清零这个计数器的接口。

8.set_by_lua_block $upstream 这里经过lua脚本给变量upstream赋值(计算的方法上文中已经明确说明过),并将这个值做为proxy_pass的参数,实现自动切换。

9.控制流量切换的是redis中的key:usCluster,将它设定为a_cluster或者b_cluster就能实现流量切换。在本身的运维平台上层再实现业务逻辑提供了很大的便利和可能。完善在线发布的流程。

相关文章
相关标签/搜索