背景:在小程序上线审核时间段内,如果后端代码直接上线到线上,如果后端不兼容上个版本的接口,可能会导致前端某些接口请求失败。不断的兼容接口,会导致代码混乱,如果是大版本的迭代,有时候也很难去兼容。在审核期间,新版本接口走灰度服务器,老接口还是走线上服务器。审核通过后,小程序和接口同时提交上线,那边就不存在什么问题了。
灰度服务总体架构
Kong 灰度服务.png
kong plugin gray服务
plugins路径
/usr/local/share/lua/5.1/kong/plugins/gray
├── client_redis.lua
├── handler.lua
└── schema.lua
handler.lua
local BasePlugin = require "kong.plugins.base_plugin"
local utils = require "kong.tools.utils"
local client_redis = require "kong.plugins.gray.client_redis"
local xml = require "pl.xml"
local function get_redis_conf(conf)
local redis_conf = {
["ip"] = conf.redis_host,
["port"] = conf.redis_port,
["passwd"] = conf.redis_password,
["timeout"]=conf.redis_timeout,
['database']=conf.redis_database}
return redis_conf
end
local GrayHandler = BasePlugin:extend()
GrayHandler.PRIORITY = 2000
function GrayHandler:new()
GrayHandler.super.new(self, "gray")
end
function GrayHandler:access(conf)
GrayHandler.super.access(self)
-- 获取版本号
local method = kong.request.get_method()
kong.log("method=" .. method)
local version
if method == "GET" then
version = kong.request.get_query_arg("v")
elseif method == "POST" then
local body, err, mimetype = kong.request.get_body()
if body ~= nil then
version = body.v
end
else
return
end
kong.log("version type=" .. type(version))
if version == nil then
return
end
local host = kong.request.get_host()
--kong.log("host=" .. host)
local arr = utils.split(host, ".")
local prefix_host = arr[1]
local key = "gray:"..prefix_host
kong.log("host=" .. host .."\tkey=" .. key)
--kong.log("host=" .. conf.redis_host.."\tport=" .. conf.redis_port.."\tpasswd=" .. conf.redis_password.."\ttimeout=" .. conf.redis_timeout.."\tdatabase="..conf.redis_database)
local redis_conf = get_redis_conf(conf)
--kong.log("timeout=" .. redis_conf['timeout'])
--local robj = client_redis:new()
local conn = client_redis:connection(redis_conf)
local gray_version,err = conn:get(key)
--kong.log("gray_version type=" .. type(gray_version))
if gray_version == ngx.null then
return
end
local log_str = "key=" .. key .. "\tversion=" .. version .. "\tgray_version=" .. gray_version
kong.log(log_str)
if version ~= nil and gray_version ~= ngx.null and gray_version == version then
local upstream = conf.upstream
kong.log(" into set upstream=" .. upstream)
local ok, err = kong.service.set_upstream(upstream)
if not ok then
kong.log.err(err)
end
end
end
return GrayHandler
schema.lua
local typedefs = require "kong.db.schema.typedefs"
return {
name = "gray",
fields = {
{ consumer = typedefs.no_consumer },
{ protocols = typedefs.protocols_http },
{ config={
type = "record",
fields = {
{ redis_host = { type = "string", required = true },},
{ redis_port = { type = "number", default = 6379 },},
{ redis_password = { type = "string", required = true},},
{ redis_database = { type = "number", default = 0},},
{ redis_timeout = { type = "number", default = 1000},},
{ upstream = { type = "string", required = true},},
}
}
}
}
}
client_redis.lua
local redis = require "resty.redis"
local _M = {}
function _M:new()
local o = {}
setmetatable(o, self)
self.__index = self;
return o
end
function _M:connection(config)
--kong.log("into redis")
--kong.log("redis:ip=" .. config['ip'] .. "\tport=" .. config['port'])
--kong.log("redis:ip=" .. config['ip'] .. "\tport=" .. config['port'] .. "\ttimeout=" .. config['timeout'])
local red = redis:new()
red:set_timeout(config['timeout'])
local ok, err = red:connect(config['ip'],config['port'])
if not ok then
ngx.log(ngx.ERR, 'failed to connection redis',err)
return nil
end
local ok, err = red:auth(config['passwd'])
if not ok then
red:close()
ngx.log(ngx.ERR, 'Auth not pass')
return nil
end
red:select(config['database'])
return red
end
return _M
将代码添加到configmap
kubectl create configmap kong-plugin-gray-cm --from-file=/usr/local/share/lua/5.1/kong/plugins/gray
gray.yaml
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: kong-plugin-gray
labels:
global: "false"
config:
redis_host: "172.16.1.1"
redis_port: 6379
redis_password: "xxxxxxx"
redis_database: 0
redis_timeout: 1000
upstream: "k8s-gray-mobile.default.80.svc"
plugin: gray
创建KongPluin
kubectl apply -f gray.yaml
ingress中注解,需要使用kong-plugin-gray插件
ingress:
enabled: true
annotations:
konghq.com/plugins: "kong-plugin-gray"
至此,整个灰度服务流程已完成。
网友评论