利用nginx+lua+memcache實現灰度發佈

1、灰度發佈原理說明html

灰度發佈在百度百科中解釋:前端

灰度發佈是指在黑與白之間,可以平滑過渡的一種發佈方式。AB test就是一種灰度發佈方式,讓一部分用戶繼續用A,一部分用戶開始用B,若是用戶對B沒有什麼反對意見,那麼逐步擴大範圍,把全部用戶都遷移到B上面 來。灰度發佈能夠保證總體系統的穩定,在初始灰度的時候就能夠發現、調整問題,以保證其影響度。nginx

 

這裏的用於WEB系統新代碼的測試發佈,讓一部分(IP)用戶訪問新版本,一部分用戶仍然訪問正常版本,其原理如圖:c++

 

 

執行過程:git

一、      當用戶請求到達前端代理服務Nginx,內嵌的lua模塊解析Nginx配置文件中的lua腳本代碼;github

二、      Lua變量得到客戶端IP地址,去查詢memcached緩存內是否有該鍵值,若是有返回值執行@client_test,不然執行@client。vim

三、      Location @client_test把請求轉發給部署了new版代碼的服務器,location @client把請求轉發給部署了normal版代碼的服務器,服務器返回結果。整個過程完成。緩存

下面把安裝配置過程詳細說明。服務器

 

2、安裝配置過程詳解app

一、安裝nginx

安裝依賴包

yum -y install gcc gcc-c++ autoconf libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel zlib zlib-devel glibc glibc-devel glib2 glib2-devel bzip2 bzip2-devel ncurses ncurses-devel curl curl-devel e2fsprogs e2fsprogs-devel krb5 krb5-devel libidn libidn-devel openssl openssl-devel openldap openldap-devel nss_ldap openldap-clients openldap-servers make pcre-devel

yum -y install gd gd2 gd-devel gd2-devel lua lua-devel

yum –y install memcached

 

下載lua模塊、lua-memcache操做庫文件和nginx包

wget https://github.com/simpl/ngx_devel_kit/archive/v0.2.18.tar.gz

wget https://github.com/chaoslawful/lua-nginx-module/archive/v0.8.5.tar.gz

wget https://github.com/agentzh/lua-resty-memcached/archive/v0.11.tar.gz

wget http://nginx.org/download/nginx-1.4.2.tar.gz

tar xvf nginx-1.4.2.tar.gz

cd nginx-1.4.2/

./configure --prefix=/soft/nginx/ --with-http_gzip_static_module --add-module=/root/ngx_devel_kit-0.2.18/  --add-module=/root/lua-nginx-module-0.8.5/

make

make install

 

拷貝lua的memcached操做庫文件

tar xvf v0.11.tar.gz

cp -r lua-resty-memcached-0.11/lib/resty/ /usr/lib64/lua/5.1/


 

配置nginx

#vim /soft/nginx/conf/nginx.conf

worker_processes  1;

events {

    worker_connections  1024;

}

http {

    include       mime.types;

    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    proxy_next_upstream     error timeout;

    proxy_redirect          off;

    proxy_set_header        Host $host;

    proxy_set_header        X-Real-IP $http_x_forwarded_for;

    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

    client_max_body_size    100m;

    client_body_buffer_size 256k;

    proxy_connect_timeout   180;

    proxy_send_timeout      180;

    proxy_read_timeout      180;

    proxy_buffer_size       8k;

    proxy_buffers           8 64k;

    proxy_busy_buffers_size 128k;

    proxy_temp_file_write_size 128k;

     upstream client {

        server   192.168.200.29:80;

    }

    upstream client_test {

        server   192.168.200.29:81;

    }

    server {

        listen       80;

        server_name  localhost;

       location / {

       content_by_lua '

            clientIP = ngx.req.get_headers()["X-Real-IP"]

            if clientIP == nil then

                clientIP = ngx.req.get_headers()["x_forwarded_for"]

            end

            if clientIP == nil then

                clientIP = ngx.var.remote_addr

            end

                local memcached = require "resty.memcached"

                local memc, err = memcached:new()

                if not memc then

                    ngx.say("failed to instantiate memc: ", err)

                    return

                end

                local ok, err = memc:connect("127.0.0.1", 11211)

                if not ok then

                    ngx.say("failed to connect: ", err)

                    return

                end

                local res, flags, err = memc:get(clientIP)

                if err then

                    ngx.say("failed to get clientIP ", err)

                    return

                end

                if  res == "1" then

                    ngx.exec("@client_test")

                    return

                end

                 ngx.exec("@client")

               

               ';

       }

       location @client{

           proxy_pass http://client;

       }

       location @client_test{

           proxy_pass http://client_test;

       }

    location /hello {

        default_type 'text/plain';

        content_by_lua 'ngx.say("hello, lua")';

    }

    location = /50x.html {

        root   html;

    }

   }

}

 

檢測配置文件。

#/soft/nginx/sbin/nginx -t

nginx: the configuration file /soft/nginx/conf/nginx.conf syntax is ok

nginx: configuration file /soft/nginx/conf/nginx.conf test is successful

 

啓動nginx

/soft/nginx/sbin/nginx

 

啓動memcached服務

memcached -u nobody -m 1024 -c 2048 -p 11211 –d

 

 

3、測試驗證

測試lua模塊是否運行正常

訪問http://測試服務器ip地址/hello。若是顯示:hello,lua 表示安裝成功。

 

 

 

在另外一臺測試機(這裏是192.168.200.29)設置兩個虛擬主機,一個用80端口是執行正常代碼,一個是81端口執行灰度測試代碼。

 

在memcached中以你的客戶機IP地址爲key,value值爲1。這裏個人IP是192.168.68.211.

telnet localhost 11211

Trying ::1...

Connected to localhost.

Escape character is '^]'.

set 192.168.68.211 0 3600 1

1

STORED

get 192.168.68.211

VALUE 192.168.68.211 9 1

1

END

quit

 

 

注意:

set後第一個值爲key值。

192.168.68.211這是key值是須要灰度測試的IP地址;

0 表示一個跟該key有關的自定義數據;

3600 表示該key值的有效時間;

1 表示key所對應的value值的字節數。

 

下面訪問Nginx,效果符合預期,個人IP已經在memcached中存儲值,因此請求轉發給執行灰度測試代碼的主機。

 

從memcached刪除個人主機IP值。

 

再次請求Nginx,請求轉發給執行正常代碼內容的主機。

 

 

整個配置並不複雜,整個判斷過程對服務的影響很是小。若是須要使用這個系統最好本身看看lua腳本。

相關文章
相關標籤/搜索