1. 程式人生 > 實用技巧 >Nginx+lua實現灰度釋出

Nginx+lua實現灰度釋出

之前簡單寫過快取預熱加上二級快取,感覺還挺好玩的,在b站看到nginx的視訊,也呼叫lua的模組,做了灰度釋出,自己做了幾個小時,結果最後失敗了,可能是虛擬機器的原因,nginx那臺經常登不上,下面就是它的主要流程。

Nginx呼叫Lua指令

Nginx呼叫Lua模組指令, Nginx的可插拔模組載入執行, 共11個處理階段

語法
set_by_lua set_by_lua_file 設定Nginx變數,可以實現負載的賦值邏輯
access_by_lua access_by_lua_file 請求訪問階段處理, 用於訪問控制
content_by_lua content_by_lua_file 內容處理器, 接受請求處理並輸出響應
變數
ngx.var nginx變數
ngx.req.get_headers 獲取請求頭
ngx.req.get_uri_args 獲取url請求引數
ngx.redirect 重定向
ngx.print 輸出響應內容體
ngx.say 輸出響應內容體,最後輸出一個換行符
ngx.header 輸出響應頭

Nginx+Lua實現程式碼灰度釋出

使用Nginx結合lua實現程式碼灰度釋出

按照一定的關係區別,分不分的程式碼進行上線,使程式碼的釋出能平滑過渡上線

1.使用者的資訊cookie等資訊區別
2.根據使用者的ip地址, 顆粒度更廣

實踐架構圖

執行過程:

  • 1.使用者請求到達前端代理Nginx, 內嵌的lua模組會解析Nginx配置檔案中Lua指令碼
  • 2.Lua指令碼會獲取客戶端IP地址,檢視Memcached快取中是否存在該鍵值
  • 3.如果存在則執行@java_test,否則執行@java_prod
  • 4.如果是@java_test, 那麼location會將請求轉發至新版程式碼的叢集組
  • 5.如果是@java_prod, 那麼location會將請求轉發至原始版程式碼叢集組
  • 6.最後整個過程執行後結束

實踐環境準備:

系統 服務 地址
CentOS7 Nginx+Lua+Memached 192.168.1.109
CentOS7 Tomcat叢集8080_Prod 192.168.1.145
CentOS7 Tomcat叢集9090_Test 192.168.1.144

1.安裝兩臺伺服器Tomcat,分別啟動80809090

[root@tomcat-node1-20 ~]# yum install java -y
[root@tomcat-node1-20 ~]# mkdir /soft/src -p
[root@tomcat-node1-20 ~]# cd /soft/src
[root@nginx ~]# wget http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-9/v9.0.7/bin/apache-tomcat-9.0.7.tar.gz
[root@tomcat-node1-20 src]# tar xf apache-tomcat-9.0.7.tar.gz  -C /soft
[root@tomcat-node1-20 soft]# cp -r apache-tomcat-9.0.7/ tomcat-8080
[root@tomcat-node1-20 bin]# /soft/tomcat-8080/bin/startup.sh
//注意tomcat預設監聽在8080埠, 如果需要啟動9090埠需要修改server.xml配置檔案

2.配置Memcached並讓其支援Lua呼叫

//安裝memcached服務
[root@Nginx-Lua ~]# yum install memcached -y

//配置memcached支援lua
[root@Nginx-Lua ~]# cd /soft/src
[root@Nginx-Lua ~]# wget https://github.com/agentzh/lua-resty-memcached/archive/v0.11.tar.gz
[root@Nginx-Lua ~]# tar xf v0.11.tar.gz
[root@Nginx-Lua ~]# cp -r lua-resty-memcached-0.11/lib/resty/memcached.lua /etc/nginx/lua/

//啟動memcached
[root@Nginx-Lua ~]# systemctl start memcached
[root@Nginx-Lua ~]# systemctl enable memcached

3.配置負載均衡排程

#必須在http層
lua_package_path "/etc/nginx/lua/memcached.lua";
upstream java_prod {
        server 192.168.1.145:8080;
}

upstream java_test {
        server 192.168.1.144:9090;
}

server {
        listen 80;
        server_name 192.168.1.109;


        location /hello {
                default_type 'text/plain';
                content_by_lua 'ngx.say("hello ,lua scripts")';
        }

        location /myip {
                default_type 'text/plain';
                content_by_lua '
                        clientIP = ngx.req.get_headers()["x_forwarded_for"]
                        ngx.say("Forwarded_IP:",clientIP)
                        if clientIP == nli then
                                clientIP = ngx.var.remote_addr
                                ngx.say("Remote_IP:",clientIP)
                        end
                        ';
        }
        location / {
                default_type 'text/plain';
                content_by_lua_file /etc/nginx/lua/dep.lua;
        }
       location @java_prod {
                proxy_pass http://java_prod;
                include proxy_params;
        }

        location @java_test {
                proxy_pass http://java_test;
                include proxy_params;
        }
}


//nginx反向代理tomcat,必須配置頭部資訊否則返回400錯誤
[root@nginx-lua conf.d]# cat ../proxy_params 
proxy_redirect default;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;

proxy_buffer_size 32k;
proxy_buffering on;
proxy_buffers 4 128k;
proxy_busy_buffers_size 256k;
proxy_max_temp_file_size 256k;

4.編寫Nginx呼叫灰度釋出Lua指令碼

[root@nginx ~]# cat /etc/nginx/lua/dep.lua 
--獲取x-real-ip
clientIP = ngx.req.get_headers()["X-Real-IP"]

--如果IP為空-取x_forwarded_for
if clientIP == nil then
    clientIP = ngx.req.get_headers()["x_forwarded_for"]
end

--如果IP為空-取remote_addr
if clientIP == nil then
     clientIP = ngx.var.remote_addr
end

--定義本地,載入memcached
    local memcached = require "resty.memcached"
--例項化物件
    local memc, err = memcached:new()
--判斷連線是否存在錯誤
    if not memc then
        ngx.say("failed to instantiate memc: ", err)
        return
    end
--建立memcache連線
    local ok, err = memc:connect("127.0.0.1", 11211)
--無法連線往前端丟擲錯誤資訊
    if not ok then
        ngx.say("failed to connect: ", err)
        return
    end
--獲取物件中的ip-存在值賦給res
    local res, flags, err = memc:get(clientIP)
--
 --ngx.say("value key: ",res,clientIP)
    if err then
        ngx.say("failed to get clientIP ", err)
        return
    end
--如果值為1則呼叫local-@java_test
    if res == "1" then
        ngx.exec("@java_test")
        return
    end
--否則呼叫local-@java_prod
        ngx.exec("@java_prod")
        return

5.使用Memcache set IP, 測試灰度釋出

//telnet傳入值
[root@nginx conf.d]# telnet 127.0.0.1 11211
# set對應IP
set 211.161.160.201 0 0 1
# 輸入1
1