基于 Nginx+lua+Memcache 实现灰度发布

一、灰度发布原理说明

灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式。AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面 来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。
这里的用于WEB系统新代码的测试发布,让一部分(IP)用户访问新版本,一部分用户仍然访问正常版本,其原理如图:
在这里插入图片描述
执行过程:

  1. 当用户请求到达前端代理服务Nginx,内嵌的lua模块解析Nginx配置文件中的lua脚本代码;
  2. Lua变量获得客户端IP地址,去查询memcached缓存内是否有该键值,如果有返回值执行@client_test,否则执行@client。
  3. Location @client_test把请求转发给部署了new版代码的服务器,location
    @client把请求转发给部署了normal版代码的服务器,服务器返回结果。整个过程完成。

下面把安装配置过程详细说明。

二、安装配置过程详解

1、安装nginx

安装依赖包

[root@master ~]# mkdir /usr/local/nginx
[root@master ~]# cd /usr/local/nginx/
[root@master ~]# 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
[root@master nginx]# yum -y install gd gd2 gd-devel gd2-devel lua lua-devel
[root@master nginx]# yum –y install memcached

下载lua模块、lua-memcache操作库文件和nginx包

[root@master nginx]# wget https://github.com/simpl/ngx_devel_kit/archive/v0.2.18.tar.gz
[root@master nginx]# wget https://github.com/chaoslawful/lua-nginx-module/archive/v0.8.5.tar.gz
[root@master nginx]# wget https://github.com/agentzh/lua-resty-memcached/archive/v0.11.tar.gz
[root@master nginx]# wget http://nginx.org/download/nginx-1.4.2.tar.gz
[root@master nginx]# tar xvf nginx-1.4.2.tar.gz
[root@master nginx]# tar -zxvf v0.2.18.tar.gz 
[root@master nginx]# tar -zxvf v0.8.5.tar.gz
[root@master nginx]# tar -zxvf v0.11.tar.gz 
[root@master nginx]# cd nginx-1.4.2/
[root@master nginx-1.4.2]# ./configure \
--prefix=/soft/nginx/ \
--with-http_gzip_static_module \
--add-module=/usr/local/nginx/ngx_devel_kit-0.2.18/ \
--add-module=/usr/local/nginx/lua-nginx-module-0.8.5/
[root@master nginx-1.4.2]# make&&make install

拷贝lua的memcached操作库文件

[root@master nginx]# cp -r lua-resty-memcached-0.11/lib/resty/ /usr/lib64/lua/5.1/

配置nginx
nginx节点ip:192.168.1.108
项目部署节点ip:192.168.1.09
在项目部署节点部署两个测试项目分别在 80 和81 端口
通过nginx配置文件映射到部署节点
配置文件中配置的ip是部署节点的ip地址

[root@master nginx]# vim /soft/nginx/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  text/html;
    sendfile        on;
    keepalive_timeout  65;
    include extra/*.conf;
    gzip on;
    gzip_min_length 5k;
    gzip_comp_level 3;
    gzip_types application/javascript image/jpeg image/svg+xml;
    gzip_buffers 4 32k;
    gzip_vary on;
}
[root@master nginx]# cd conf/
[root@master conf]# mkdir extra
[root@master conf]# cd extra/
[root@master extra]# vim proxy_demo.conf 
upstream client {
    server   192.168.0.129:80;
    server   192.168.0.129:9090;
}
upstream client_test {
    server   192.168.0.129:81;
}
server {
    listen       80;
    server_name  localhost;
    location / {
        #客户端请求ip
        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;
        #请求转发出错时的配置 proxy_next_upstream [error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 |http_404 | off ];
        proxy_next_upstream     error timeout;
        #用于设置nginx与upstream server的连接超时时间,比如我们直接在location中设置proxy_connect_timeout1ms, 1ms很短,如果无法在指定时间建立连接,就会报错。
        proxy_connect_timeout   180;
        #向后端写数据的超时时间,两次写操作的时间间隔如果大于这个值,也就是过了指定时间后端还没有收到数据,连接会被关闭
        proxy_send_timeout      180;
        #从后端读取数据的超时时间,两次读取操作的时间间隔如果大于这个值,那么nginx和后端的链接会被关闭,如果一个请求的处理时间比较长,可以把这个值设置得大一些
        proxy_read_timeout      180;
        #允许来自所有的访问地址
        add_header 'Access-Control-Allow-Origin' '*';
        #支持的请求方式
        add_header 'Access-Control-Allow-Methods' 'GET,PUT,POST,DELETE,OPTIONS';
        #支持的媒体类型
        add_header 'Access-Control-Allow-Header' 'Content-Type,*';
        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;
    }
}

检测配置文件。

[root@master conf]# /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

[root@master conf]# /soft/nginx/sbin/nginx

重新读取nginx配置文件命令

[root@master nginx]# cd sbin/
[root@master sbin]# ./nginx -s reload

启动memcached服务

[root@master conf]# yum install -y memcached
[root@master conf]# memcached -u nobody -m 1024 -c 2048 -p 11211 –d

三、测试验证

测试lua模块是否运行正常
访问http://测试服务器ip地址/hello。如果显示:hello,lua 表示安装成功。

项目部署节点192.168.1.109,部署两个测试项目,一个用80端口是执行正常代码,一个是81端口执行灰度测试代码。
在memcached中以你的客户机IP地址为key,value值为1。这里我的IP是192.168.1.100

[root@master ~]# yum install -y telnet 
[root@master ~]# telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
set 192.168.1.100 0 3600 1
1
STORED
get 192.168.1.100
VALUE 192.168.1.100 0 1
1
END
quit
Connection closed by foreign host.

注意:
set后第一个值为key值。
192.168.1.100这是key值是需要灰度测试的IP地址;
0 表示一个跟该key有关的自定义数据;
3600 表示该key值的有效时间;
1 表示key所对应的value值的字节数。
下面访问Nginx节点192.168.1.108,nginx会映射到192.168.1.109节点的80和81端口,效果符合预期,我的IP已经在memcached中存储值,所以请求转发给执行灰度测试代码的主机。
在这里插入图片描述
最后删除灰度测试代码主机,来测试访问生产环境

[root@master ~]# telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
delete 192.168.1.100
DELETED

删除成功,重新访问nginx,进入到生产环境项目
在这里插入图片描述
nginx搭建完成!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值