Openresty+Redis 動態切換upstream

場景
當版本切換的時候,後端服務器不可能瞬間同時進行代碼更新,這樣就會出現客戶在短暫時間內訪問到不同版本的服務。

使用以下流程可以避免上述問題:
1.後端設立兩個的主機組(A_CLUSTER,B_CLUSTER),以及一個ALL_CLUSTER包含兩個主機組提供服務。
2.當要發佈前,將所有的流量切換到B_CLUSTER。
3.切換完畢後升級A_CLUSTER代碼。
4.將流量再切換到A_CLUSTER。
5.再升級B_CLUSTER的代碼。
6.最後將流量再切換至兩CLUSTER。

要完成上述操作,在代碼更新方面有jenkins等發佈工具來實現。但前端切換流量的在傳統中只能通過手動修改nginx配置文件來實現。

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數值,然後保存在內存中,並使用這個設定。

3.這樣除了需要在redis中保存數據,還需要在openrestry中保存當前upstream以及訪問次數的數據。

4.lua_shared_dict vtimes 10m;開闢了一個共享內存空間,可以將數據以key-value形式保存到內存內。

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就能實現流量切換。在自己的運維平臺上層再實現業務邏輯提供了很大的便利和可能。完善在線發佈的流程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章