灰度發佈,灰度發佈(又名金絲雀發佈)是指在黑與白之間,能夠平滑過渡的一種發佈方式。在其上可以進行A/B testing,即讓一部分用戶繼續用產品特性A,一部分用戶開始用產品特性B,如果用戶對B沒有什麼反對意見,那麼逐步擴大範圍,把所有用戶都遷移到B上面來。灰度發佈可以保證整體系統的穩定,在初始灰度的時候就可以發現、調整問題,以保證其影響度。
Nginx+Lua 實現灰度發佈
一、概念
灰度發佈概念
按照一定的關係區分,分不分的代碼進行上線,使代碼的發佈能平滑過渡上線
△使用用戶的信息cookie等信息區別
△根據用戶的ip地址區分 (本次使用ip地址區分)
灰度發佈(又名金絲雀發佈)是指在黑與白之間,能夠平滑過渡的一種發佈方式。在其上可以進行A/B testing,即讓一部分用戶繼續用產品特性A,一部分用戶開始用產品特性B,如果用戶對B沒有什麼反對意見,那麼逐步擴大範圍,把所有用戶都遷移到B上面來。灰度發佈可以保證整體系統的穩定,在初始灰度的時候就可以發現、調整問題,以保證其影響度。
灰度期:灰度發佈開始到結束期間的這一段時間,稱為灰度期。
這裡用於WEB系統新代碼的測試發佈,讓一部分(IP)用戶訪問新版本,一部分用戶仍然訪問正常版本,其原理如圖:
二、環境準備
2.1 安裝LUA環境及相關庫
模塊目錄全部放在/opt/下
<code>#安裝LuaJITwget -P /opt/ http://down.i4t.com/LuaJIT-2.0.5.tar.gztar xf LuaJIT-2.0.5.tar.gzcd LuaJIT-2.0.5make && make installecho "export LUAJIT_LIB=/usr/local/lib" >>/etc/profileecho "export LUAJIT_INC=/usr/local/include/luajit-2.0" >>/etc/profilesource /etc/profile/<code>
ngx_devel_kit和lua-nginx-module都是lua需要的模塊
<code>#下載ngx_devel_kit模塊wget -P /opt/ http://down.i4t.com/ngx_devel_kit-0.3.0.tar.gztar xf ngx_devel_kit-0.3.0.tar.gz#下載lua-nginx-module模塊wget -P /opt/ http://down.i4t.com/lua-nginx-module-0.10.13.tar.gztar xf lua-nginx-module-0.10.13.tar.gz/<code>
還需要安裝redis2-nginx-module模塊
redis2-nginx-module 是一個支持 Redis 2.0 協議的 Nginx upstream 模塊,它可以讓 Nginx 以非阻塞方式直接防問遠方的 Redis 服務,同時支持 TCP 協議和 Unix Domain Socket 模式,並且可以啟用強大的 Redis 連接池功能
<code>wget -P /opt/ http://down.i4t.com/redis2-nginx-module-0.15.tar.gztar xf redis2-nginx-module-0.15.tar.gz/<code>
接下來就是安裝Nginx了,版本我們採用目前穩定版1.14
<code>#下載nginxwget -P /opt/ http://down.i4t.com/nginx-1.14.2.tar.gztar xf nginx-1.14.2.tar.gz/<code>
現在進行編譯安裝nginx
<code>1.安裝依賴包yum install -y gcc glibc gcc-c++ prce-devel openssl-devel pcre-devel lua-devel libxml2 libxml2-devel libxslt-devel perl-ExtUtils-Embed GeoIP GeoIP-devel GeoIP-data zlib zlib-devel openssl pcre pcre-devel gcc g++ gcc-c++ gd-devel2.創建用戶useradd -s /sbin/nologin nginx -M3.編譯安裝nginxcd /opt/nginx-1.14.2./configure --prefix=/usr/local/nginx-1.14.2 \\--user=nginx --group=nginx --with-http_ssl_module \\--with-http_stub_status_module \\--add-module=/opt/lua-nginx-module-0.10.13 \\--add-module=/opt/ngx_devel_kit-0.3.0 \\--add-module=/opt/redis2-nginx-module-0.15#必須按照我的版本來,否則會出現問題make && make install#設置軟連ln -s /usr/local/nginx-1.14.2 /usr/local/nginx#設置模塊,否則nginx -t報錯ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2錯誤提示如下:/usr/local/nginx/sbin/nginx -t/usr/local/nginx/sbin/nginx: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory/<code>
三、Nginx配置Lua
在nginx編譯之後,我們需要先檢查一下lua是否安裝成功
1.首先檢查nginx服務是否正常
2.驗證lua模塊是否成功
<code>location /test { default_type 'text/plain'; content_by_lua 'ngx.say("test")'; }/<code>
3.reload nginx檢查是否正常
<code>[root@abcdocker ~]# vim /usr/local/nginx/conf/nginx.conf[root@abcdocker ~]# /usr/local/nginx/sbin/nginx -tnginx: the configuration file /usr/local/nginx-1.14.2/conf/nginx.conf syntax is oknginx: configuration file /usr/local/nginx-1.14.2/conf/nginx.conf test is successful[root@abcdocker ~]# /usr/local/nginx/sbin/nginx -s reload[root@abcdocker ~]# curl 127.0.0.1/testtest/<code>
當訪問/test時返回值也為test代表沒有問題,也可以在瀏覽器訪問
四、安裝redis
<code>#yum安裝yum install epel-releaseyum repolistyum install redis -y#修改redis ipsed -i 's/127.0.0.1/0.0.0.0/g' /etc/redis.conf#啟動服務service redis start[root@abcdocker logs]# ps -ef|grep redisredis 24334 1 1 05:04 ? 00:00:00 /usr/bin/redis-server 10.4.82.138:6379root 24349 14935 0 05:04 pts/0 00:00:00 grep --color=auto redis#檢查Telnet是否正常[root@abcdocker logs]# telnet 10.4.82.138 6379Trying 10.4.82.138...Connected to 10.4.82.138.Escape character is '^]'./<code>
編譯安裝:https://i4t.com/2796.html
五、接下來修改Nginx配置文件,引用lua腳本
1.下載加載lua庫的redis腳本文件
<code>cd /optgit clone https://github.com/openresty/lua-resty-redis.gitcd lua-resty-redis/make && make install#當make完畢之後會生成我們的路徑,複製相關路徑就可以ll /usr/local/lib/lua/resty/redis.lua/<code>
2.創建lua腳本
<code>#創建lua目錄mkdir /usr/local/nginx/conf/lua#腳本內容如下cat > /usr/local/nginx/conf/lua/abcdocker.lua <<eoflocal>/<code>
2.修改nginx.conf,引用redis.lua腳本
<code>cat /usr/local/nginx/conf/nginx.conf user nginx;worker_processes 1;events { worker_connections 1024;}http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; lua_package_path "/usr/local/lib/lua/resty/redis.lua"; lua_shared_dict ip_blacklist 1m; server { listen 80; server_name localhost; location / { lua_code_cache off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; content_by_lua_file "/usr/local/nginx/conf/lua/script/redis.lua"; } location @prod1 { proxy_pass http://10.4.82.140:8080; } location @prod2 { proxy_pass http://10.4.82.138:8080; } }}#在http標籤添加lua變量及i4t.conf#lua_package_path "/usr/local/lib/lua/resty/redis.lua";#lua腳本路徑#lua_shared_dict ip_blacklist 1m; 共享內存區域始終由當前nginx服務器實例中的所有nginx工作進程共享#content_by_lua_file 自定義lua腳本路徑#lua_code_cache nginx配置中將lua_code_cache配置成on/off來控制是否關閉lua 的cache緩存,如果設置為off.則每次修改lua腳本都會重新加載新的lua代碼,從而實現快速調試響應。同時狀態為off時啟動或重啟nginx都會提示:nginx: [alert] lua_code_cache is off; this will hurt performance in /path/to/nginx.conf。因為這會影響nginx性能表現。一般開發調試的時候使用off, 線上運行時設置為on。#localtion @prod1代表環境1#localtion @prod2代表環境2#更多變量地址:https://github.com/openresty/lua-nginx-module/<code>
啟動
<code>$ /usr/local/nginx/sbin/nginx -tnginx: [alert] lua_code_cache is off; this will hurt performance in /usr/local/nginx-1.14.2/conf/nginx.conf:22nginx: the configuration file /usr/local/nginx-1.14.2/conf/nginx.conf syntax is oknginx: configuration file /usr/local/nginx-1.14.2/conf/nginx.conf test is successful#這裡的警告可以忽略,是由於lua_code_cache為off影響的/<code>
接下來就是部署2臺tomcat
10.4.82.138 8080
10.4.82.140 8080
我這裡就不寫安裝了,不會的可以參考下面文檔
企業必會tomcat https://i4t.com/2514.html
當我們默認訪問的時候,不修改redis參數,不加任何變量訪問的是prod2環境
默認訪問如下圖
接下來我們進入到redis裡面,讓我們這個ip訪問成prod1環境
這裡的腳本邏輯解釋如下
redis Key 為0 訪問Pord1
redis Key 為空 訪問Pord2
redis Key 為1 訪問Pord2
我們修改過nginx之後再次訪問10.4.82.138 項目就變為tomcat代碼了
Lua腳本可以進行自定義,我這裡只是簡單的實現,後期會考慮使用cookie實現~
閱讀更多 花絮大咖 的文章