浅谈基于openresty(nginx+lua)开发轻量级,按流量控制的灰度模块(下)

简介: 浅谈基于openresty(nginx+lua)开发轻量级,按流量控制的灰度模块
  • ·灰度模块开发(proxy.lua)
  -- Copyright (C) www.bytearch.com (iyw)
    local config = require("gray.config")
    -- 按流量灰度
    local _M = {
        _VERSION = "0.0."
    }
    -- request count
    local req_count = 0;
    local uri_req_count_map = {}
    local function _getRequestUri()
        local uri = ngx.var.uri
        return uri
    end
    -- write api transmit to new api
    local function _isProxyNewMust()
        local proxy_new_uri_list = config['must_proxy_new_uri_list']
        if proxy_new_uri_list[_getRequestUri()] then
            return true
        end
        return false;
    end
    local function _checkWhiteReq()
        local headers = ngx.req.get_headers()
        local white_ip_list = config['white_ip_list']
        local ip = headers["X-REAL-IP"] or headers["X_FORWARDED_FOR"] or ngx.var.remote_addr or "0.0.0.0"
        for _, v in ipairs(white_ip_list) do
            if v == ip then
                return true
            end
        end
        return false
    end
    local function _getReqCnt()
        req_count = req_count + 1
        return req_count;
    end
    local function _getReqCountByKey(key)
        local req_count = uri_req_count_map[key]
        if req_count == nil then
            req_count = 0
        end
        uri_req_count_map[key] = req_count + 1
        return uri_req_count_map[key]
    end
    local function _getUpstreamByUriAndCount()
        local proxy_sys_level = config['proxy_sys_level']
        local old_upstream = config['old_upstream']
        local new_upstream = config['new_upstream']
        local proxy_percent = config['proxy_percent']
        -- system level
        if proxy_sys_level == 2 then
            return old_upstream
        elseif proxy_sys_level == 1 then
            return new_upstream
        else
            if _checkWhiteReq() == true then
                return new_upstream
            end
            -- write first
            if _isProxyNewMust() == true then
                return new_upstream
            end
            local uri = _getRequestUri()
            -- proxy cantain uri
            local proxy_uri_list = config['proxy_uri_list']
            if uri and proxy_uri_list[uri] then
                local count = _getReqCountByKey(uri)
                if (count % proxy_percent.base) < proxy_percent.new then
                    return new_upstream
                end
            end
            return old_upstream
        end
    end
    function _M.init()
        local upstream = _getUpstreamByUriAndCount();
        ngx.var.backend = upstream
    end
    return _M

4.测试

  • ·test_old.conf 9001端口
server{
    listen 9001;
    server_name localhost;
    index index.html index.do;
    access_log logs/index_access.log;
    error_log  logs/index_error.log info;
    charset utf-8;
    default_type 'text/html';
    location ~ /write {
        content_by_lua '
            ngx.say("old write api")
        ';
    }
    location ~ /(.*){
        set $proxy_uri $1;
        content_by_lua '
            ngx.say("<h2> Old Api, uri:", ngx.var.proxy_uri , "</h2>")
        ';
    }
}
  • ·反向代理 9000端口
#此处配置新老系统地址
upstream proxy_old {
    server localhost:9001 max_fails=3 fail_timeout=2s;
    keepalive 32;
}
upstream proxy_new {
    server localhost:9002 max_fails=3 fail_timeout=2s;
    keepalive 32;
}
server{
    listen 9000;
    server_name localhost;
    index index.html index.do;
    access_log logs/index_access.log;
    error_log  logs/index_error.log info;
    charset utf-8;
    default_type 'text/html';
    ## 注意: lua_code_cache需要设置为on
    lua_code_cache on;
    location ~* /(.*) {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;
        set $backend "proxy_old";
        rewrite_by_lua_block  {
              local proxy = require("gray.proxy");
              if proxy then
                   proxy.init()
              end
        }
        proxy_pass http://$backend;
    }
}

更改配置proxy_percent.new = 5,  proxy_percent.base = 100 (即5%流量转发到新系统),将配置加入到openresty配置并启动

  最后测试结果如下


5.总结

实际场景可能更为复杂,比如可能会根据请求参数灰度策略,这些都可以根据实际很容易情况定制开发。以上源代码请查看: https://github.com/bytearch/gray , 欢迎star,谢谢大家!

相关文章
|
域名解析 负载均衡 网络协议
双重神器合璧,流量洪流中的稳如磐石:揭秘Bind+Nginx负载均衡的超级力量!
【8月更文挑战第9天】在现代网站架构中,负载均衡至关重要,它通过分散客户端请求至多台服务器,确保了系统的高可用性和稳定性。本文介绍如何结合Bind与Nginx实现高效负载均衡。Bind作为DNS服务器,可为单一域名解析出多个IP地址;Nginx作为高性能HTTP服务器,则在这些IP对应的服务器间智能分配流量。通过配置Bind的A记录与Nginx的`upstream`和`proxy_pass`指令,我们能够构建一个既稳定又易扩展的负载均衡系统,显著提升用户体验与系统可靠性。
357 11
|
负载均衡 应用服务中间件 网络安全
Django后端架构开发:Nginx服务优化实践
Django后端架构开发:Nginx服务优化实践
320 2
|
应用服务中间件 nginx
[nginx]编译安装openresty
[nginx]编译安装openresty
879 6
|
应用服务中间件 Linux nginx
FFmpeg开发笔记(四十)Nginx集成rtmp模块实现RTMP推拉流
《FFmpeg开发实战》书中介绍了如何使用FFmpeg向网络推流,简单流媒体服务器MediaMTX不适用于复杂业务。nginx-rtmp是Nginx的RTMP模块,提供基本流媒体服务。要在Linux上集成rtmp,需从官方下载nginx和nginx-rtmp-module源码,解压后在nginx目录配置并添加rtmp模块,编译安装。配置nginx.conf启用RTMP服务,监听1935端口。使用ffmpeg推流测试,如能通过VLC播放,表明nginx-rtmp运行正常。更多详情见书本。
778 0
FFmpeg开发笔记(四十)Nginx集成rtmp模块实现RTMP推拉流
|
Ubuntu 应用服务中间件 Linux
Linux学习之Ubuntu 20中OpenResty的nginx目录里内容和配置文件
总的来说,OpenResty的Nginx配置文件是一个强大的工具,它允许你以非常灵活的方式定义你的Web服务的行为。
600 2
|
应用服务中间件 nginx
[nginx]lua读取请求体
[nginx]lua读取请求体
353 0
|
缓存 应用服务中间件 nginx
[nginx]lua控制响应头
[nginx]lua控制响应头
465 0
|
应用服务中间件 API nginx
[nginx]lua控制请求头
[nginx]lua控制请求头
458 0
|
JavaScript Ubuntu 应用服务中间件
nginx扩展 OpenResty 实现防cc攻击教程
使用OpenResty实现CC攻击防护,包括两个主要步骤:限制请求速度和JS验证。首先,安装依赖(RHEL/CentOS需安装readline-devel, pcre-devel, openssl-devel,Ubuntu需安装libreadline-dev等)。然后,安装Luajit和OpenResty。在Nginx配置中,创建`lua`共享字典并设置`content_by_lua_file`调用lua脚本。lua脚本检查请求频率,超过限制则返回503,否则增加计数。同时,通过JS验证,生成随机码并重定向用户,用户需携带正确验证码请求才能访问。
608 0
|
存储 安全 应用服务中间件
解密Nginx限流机制:有效应对DDoS攻击与高并发流量
解密Nginx限流机制:有效应对DDoS攻击与高并发流量
622 0
下一篇
开通oss服务