OpenResty实现按租户灰度发布

Posted isea533

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenResty实现按租户灰度发布相关的知识,希望对你有一定的参考价值。

K8s上的一套SaaS服务,每个租户都有自己的独立数据库,前后端分离,后端微服务,前端nginx

当SaaS服务升级的时候,需要按照租户逐个进行升级,因此升级过程中需要逐步将租户迁移到新的服务上,后端基于 Spring Cloud Gateway 实现,前端通过 OpenResty 结合 K8s Service 实现。

OpenResty 配置代码

基础代码如下:

worker_processes  1;
error_log logs/error.log debug;
events 
    worker_connections 1024;


http 

    # 确定要请求哪个HTTP服务
    access_by_lua_block 
        -- 使用 redis 获取租户信息,为了lua代码高亮,代码放在后面单独块中
    

    # 通过负载均衡方式选择后端服务
    upstream backend 
        server nginx-ui-service:80;   # 默认前端服务,使用 K8s Service

        balancer_by_lua_block 
            -- 根据租户信息进行负载均衡,为了lua代码高亮,代码放在后面单独块中
        

        keepalive 10;  # connection pool
    

    server 
        # this is the real entry point
        listen 80;

        location / 
            # make use of the upstream named "backend" defined above:
            proxy_pass http://backend;
        
    


这里主要用到了两个指令 access_by_lua_blockbalancer_by_lua_block,在前一个指令中获取租户信息,在第二个中根据获取的信息执行负载均衡。

access_by_lua_block 大括号中的代码:

-- 请求头: ngx.header.tenant
-- 示例从 url 参数获取租户信息
local arg = ngx.req.get_uri_args()
if nil == arg.tenant then
    return
end

local redis = require "resty.redis"

local red = redis:new()
red:set_timeouts(1000, 1000, 1000)

-- K8s Service: redis-server
local ok, err = red:connect("redis-server", 6379)
if not ok then
    ngx.say("failed to connect: ", err)
    return
end
-- 获取 host
local res, err = red:get("tenant:"..arg.tenant..":host")
if res ~= ngx.null then
    ngx.ctx.tenant_host = res
else
    ngx.log(ngx.INFO, "tenant: " .. arg.tenant .. " 没有配置")
end
-- 获取端口
res, err = red:get("tenant:"..arg.tenant..":port")
if res ~= ngx.null then
    ngx.ctx.tenant_port = res
else
    -- 默认值 80
    ngx.ctx.tenant_port = 80
end

ok, err = red:set_keepalive(10000, 100)
if not ok then
    ngx.say("failed to set keepalive: ", err)
    return
end

从redis读取租户信息,如果不存在后续会用默认路由,如果有就存到 ngx.ctx 中。

balancer_by_lua_block 中的内容:

local balancer = require "ngx.balancer"

if nil ~= ngx.ctx.tenant_host then
    local ok, err = balancer.set_current_peer(ngx.ctx.tenant_host, ngx.ctx.tenant_port)
    if not ok then
        ngx.log(ngx.ERR, "failed to set the current peer: ", err)
        return ngx.exit(500)
    end
end

读取 ngx.ctx 中的租户信息,然后设置负载均衡的地址。

灰度流程

  1. 当前 nginx-ui-service Service 选择的 V1 版本的前端服务。
  2. 启动 V2 版本的前端服务。
  3. 当租户的前后端都升级为最新版本后,在 redis 设置租户 tenant:1:host 要选择的服务版本 V2
  4. 当所有租户都升级到V2后,切换 nginx-ui-service Service 选择的 V2 版本的前端服务。
  5. 清除所有租户 redis 中的服务版本信息。

以上是关于OpenResty实现按租户灰度发布的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud 多租户灰度设计

Spring Cloud 多租户灰度设计

Spring Cloud 多租户灰度设计

Mybatisplus搭建多租户模式(共享库表,按租户id字段区分租户)

mysql按照租户同步

java B2B2C 多租户电子商城系统