• nginx+lua+redis实现灰度发布_test


    nginx+lua+redis实现灰度发布:

    灰度发布是指在黑白之间能够平滑过渡的一种方式

    AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面 来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。

    灰度发布可以保证应用系统的稳定,降低产品升级影响的用户范围;也可以按照一定的策略让部分用户提前参与产品测试,从而提早获取到用户的反馈,完善应用功能

    原理:使用nginx做负载均衡和反向代理,nginx内嵌lua模块,解析并执行lua编写的脚本逻辑,可以通过lua解析cookie以及访问redis,而一些灰度发布分流的策略就是放在redis里通过cookie关联

    执行过程:

    • 当用户请求到达前段代理服务nginx,內嵌的lua模块解析nginx配置文件中的lua脚本代码
    • lua变量获取到客户端的ip地址,去查询redis缓存内是否有该建值,如果有返回值执行@client_test,否则执行@client
    • location @client_test把请求转发给部属了new版代码服务器,location@client把请求转发给部属了normal版代码的服务器,localtion@client把请求转发给部属了normal版本代码的服务器,服务器返回结果。整个过程完成

    安装配置过程详解:

    1. 安装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;
    
        }
    
       }
    
    }

    检测配置文件:

    /usr/local/nginx/sbin/nginx -t

    出现ok显示成功

    启动nginx

    /usr/local/nginx/sbin/nginx

    启动memchaed服务

    chkconfig --level 2345 memcached on

    /etc/init.d/memcached start|stop

    测试lua模块是否运行正常

    telnet localhost 11211
    
    Trying ::1...
    
    Connected to localhost.
    
    Escape character is '^]'.
    
    set 192.168.68.211 0 3600 1
    
    STORED
    
    get 192.168.68.211
    
    VALUE 192.168.68.211 9 1
    
    END
    
    quit

    注意:

    set后第一个值为key值。

    192.168.68.211这是key值是需要灰度测试的IP地址;

    0 表示一个跟该key有关的自定义数据;

    3600 表示该key值的有效时间;

    1 表示key所对应的value值的字节数。

    下面访问Nginx,效果符合预期,我的IP已经在memcached中存储值,所以请求转发给执行灰度测试代码的主机。

    访问http://测试服务器ip地址/hello  如果显示lua表示安装成功

    在另一台测试机(这里是192.168.200.29)设置两个虚拟主机,一个用80端口是执行正常代码,一个是81端口执行灰度测试代码。

    在memcached中以你的客户机IP地址为key,value值为1。这里我的IP是192.168.68.211.

    从memcached删除我的主机IP值。

    再次请求Nginx,请求转发给执行正常代码内容的主机。

    整个配置并不复杂,整个判断过程对服务的影响非常小。如果需要使用这个系统最好自己看看lua脚本。

  • 相关阅读:
    关于GET和POST请求的区别,最通俗全面的回答
    Mac常用命令行
    Jquery中的done() fail() then() $when()到底是什么
    聊聊HTML5中的Web Notification桌面通知
    css实现左右两个div等高
    css样式优先级计算规则
    vue获取后端数据放在created还是mounted方法里面?
    vue的provide和inject特性
    前端路由的实现原理
    Windows鼠标右键新建中增加新建md文件
  • 原文地址:https://www.cnblogs.com/yaozhiqiang/p/9876881.html
Copyright © 2020-2023  润新知