- ·灰度模块开发(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,谢谢大家!