github代码:https://github.com/singgel/nginx-luaDemo/

一. 需求背景

需要把旧的推荐服务逐步切换到新的推荐服务上,需要灰度切换,流量比例和灰度策略可以控制。

 

二. 方案

当前数据请求流程是:外部请求—>易车nginx --->后端服务 ;

经过跟运维沟通发现,目前易车nginx 是公司级别的 不允许某个业务对配置的修改,所以我们在易车nginx 和 后端服务之间添加了一个新的转发组件;已经跟运维沟通过该方案可行。
小流量数据请求流程为:外部请求--->易车nginx---->小流量转发组件—>后端服务

目前对于转发组件的选型有两种:

1.使用nginx + lua来实现

2.使用openresty

经过调研我们打算使用的转发组件是  openresty 方案,在原有业务之上加入openresty代理,使用lua来控制流量比例和灰度策略;

 

OpenResty是在nginx的基础上,集成了很多第三方模块,比如默认带了lua模块,开发人员可以使用Lua语言对Nginx进行脚本编程,很多第三方模块跟openresty更加兼容,比如

https://github.com/openresty/lua-nginx-modulehttps://github.com/openresty/lua-resty-redis这些都是openresty的第三方模块,不过兼容nginx罢了。另外安装openresty有自己的repo仓库,安装其第三方模块也很简单方便;

该方案在 360 ,新浪等公司有较为成熟的运用;

具体安装配置方案已经在测试环境测试成功,具体如下诉 OpenResty方案测试

 

三.上线前准备:

  1. 在线上部署openresty
  2. 将易车ng 跟后端服务之间配置 转发
  3. 上线新的推荐逻辑
  4. 启动灰度策略

 

四.部署方案:

  1. 在首鸣机房部署好新的推荐服务并验证通过,首鸣机房只部署新的推荐服务
     
  2. 准备openResty ,部署在M5  机房 推荐服务api 所在的机器上,共十台机器部署10个openResty 。
       openResty 分流策略存储在redis ,默认策略是100%流量进入旧的推荐服务;当无法获取redis策略时,所有流量进入旧的推荐服务;
       业务请求进入入口nginx (目前在M5机房) 会轮询到 10 台 openResty ,当策略切换时只用修改响应的redis key 对应的值,不操作openResty ,解耦操作;
       openResty 经过策略计算 将90%的请求轮询到 M5 所在的旧的推荐api 上, 将10%的请求通过机房专线轮询到首鸣所在的推荐服务上。
     
  3. 部署好openResty 并验证通过之后,在修改入口ng转发地址
  4. 部署大致示意如下:

 

 

 

可能存在的问题:跨机房严重依赖内网专线,内网专线属于机房间内部线路,发生故障后维修时间难以保证,以天级别计算,存在重大隐患。

针对上述问题,我们的解决方案是,当流量进入M5之后,在openResty根据小量策略做判断,命中策略之后直接通过新服务域名转发到新推荐服务,未命中策略则还走之前的老的服务。

经过跟运维的沟通,通过域名转发请求的时候 会有限使用专线,如果专线有故障则会走公网;公网跟专线之间的切换由运维同事完成。

 

五.  待完成事项:

  1. 根据业务需求编写策略分流以及分流比例的脚本;
  2. 测试把策略保存到redis中,lua脚本定时从redis获取策略;

六. OpenResty方案测试

  1.  机器列表

    192.168.87.237 // 部署openresty + lua, 实现灰度策略

    172.20.4.127 // 部署业务1,测试环境使用nginx静态页代替

    192.168.15.47 // 部署业务2, 测试环境使用nginx静态页代替

  2.  代理机器192.168.87.237部署openresty + lua:

    // 安装openresty+lua, 参考http://openresty.org/cn/installation.html, http://openresty.org/cn/linux-packages.html, 这里使用预编译包:

     

    // 添加centos openresty repo

    yum install yum-utils

    yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo

     

    // install openresty with yum    

    yum install openresty

    // 新建test.lua.yiche.com vhost

    mkdir /usr/local/openresty/nginx/conf.d

    cat /usr/local/openresty/nginx/conf.d/test.lua.yiche.com.conf  // 内容如下

    init_by_lua_file        /usr/local/openresty/site/lualib/init.lua;  # lua初始化脚本

    upstream tomcat_a.domian.com {

       server 172.20.4.127;

    }

    upstream tomcat_b.domain.com {

        server 192.168.15.47;

    }

    server {

       listen 80;

       server_name  test.lua.yiche.com;

       set $default_backend 'tomcat_a.domian.com';

       location / {

           proxy_next_upstream     http_500 http_502 http_503 http_504 error timeout;

           proxy_set_header        Host  'test.lua.yiche.com';

           proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

           expires                 0;

           set $backend $default_backend;

           rewrite_by_lua_file "/usr/local/openresty/site/lualib/diversion.lua";  # 分流策略, 此脚本不会被一直缓存,改完以后不用reload配置也会片刻后就生效

           proxy_pass http://$backend;

       }

    }

     

     

    // 编辑初始化全局设置脚本

    cat /usr/local/openresty/site/lualib/init.lua

    global_configs = {

     ["divEnable"] = true  -- 分流开关

    }

     

    // 编辑分流策略脚本, 测试样例是如果分流开关开启,参数p如果是数字类型,请求转发到一个backend;参数p如果是字符串类型,请求转发到另外一个backend;

    cat /usr/local/openresty/site/lualib/diversion.lua

    if not global_configs["divEnable"] then

      return

    end

    local p = ngx.var.arg_p 

    if p then

     local nump = tonumber(p);

     if nump then

         ngx.var.backend = "tomcat_a.domian.com"

     else

         ngx.var.backend = "tomcat_b.domain.com"

     end

    end


     

  3. 后端业务机器,使用nginx静态页面代替业务

    172.20.4.127192.168.15.47增加vhost,分别在/usr/share/nginx/html下放置一个静态页testlua.html, 页面编辑为不同的内容便于观察

     server {

        listen       80;

        server_name  test.lua.yiche.com;

        access_log  /var/log/nginx/test.lua.yiche.com.access.log  main;

        location / {

            root   /usr/share/nginx/html;

            index  index.html index.htm;

        }

     

  4. 测试, 本地绑定host (192.168.87.237 test.lua.yiche.com)

    (1)访问http://test.lua.yiche.com/testlua.html?p=11,  p设置为数字类型,页面访问到了172.20.4.127

       


    (2)访问http://test.lua.yiche.com/testlua.html?p=ss,  p设置为字符串类型,页面访问到了192.168.15.47

      

 

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐