0. 前言

之前的文章谈了蓝绿部署、灰度发布,今天让我们来动手实践一下。我们提前准备好两个WEB服务如下:

image

1. 无感知发布

这里我们使用Nginx的负载均衡来实现用户无感知发布,主要就是我们提供两台服务,当需要发布的时候一台一台的进行滚动升级,利用Nginx的负载均衡特性来实现用户无感知。

Nginx配置片段如下

upstream bobbytest {
        server 192.168.1.108:9081;
        server 192.168.1.108:9082;
}

server {
    listen 8888;
    location / {
        proxy_pass  $scheme://bobbytest; 
    }
}

该配置只是简单的测试使用,使用到生产环境时,根据自己的情况进行配置。

2. 使用OpenResty实现灰度发布

2.1. OpenResty简介

OpenResty是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

OpenResty通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。

2.2. OpenResty安装

可以根据自己的需求参照官方文档进行安装 http://openresty.org/cn/installation.html

2.3. 原理说明

  • 用户的Token对应的用户ID,灰度用户ID列表存放在Redis中
  • 使用OpenResty提供的一些Nginx模块来进行判断请求用户具体引流到哪台服务

2.4. Nginx的server配置

server {

	listen 9999;
	
	location / {
		default_type text/html;
		# 执行指定的lua文件
		content_by_lua_file /root/bobbytest/lua/test.lua;
	}
	
	# 主服务
    location @MainServer {
		proxy_pass http://127.0.0.1:9081;
	}
	
	# 灰度服务
	location @GrayscaleServer {
		proxy_pass http://127.0.0.1:9082;
	}
	
}

2.5. 灰度lua文件

-- 链接Redis
local redis = require "resty.redis"
local red = redis:new()
local ok, err = red:connect("192.168.1.105", 6379)

if not ok then
	ngx.say("failed to connect: ", err)
	return
end

-- 获取用户token
local token = ngx.req.get_headers()["Authorization"]
if token ~= nil then
	-- 通过token获取用户id
	local userId = red:get(token)
	-- 判断是否是灰度范围用户
	local isGrayscale, err = red:smismember("GRAYSCALE_USER_IDS", userId)
	if isGrayscale[1] == 1 then
		-- 符合灰度条件的用户走灰度服务
		ngx.exec("@GrayscaleServer")
		return
	end
end

-- 默认走主服务
ngx.exec("@MainServer")

2.6. 测试

Redis存放测试数据如下
image-1680429870201

测试数据如下
image-1680429995430

3. End

类似的实现用户无感知发布、灰度发布的方式还有很多。比如使用一些网关中间件,如Apache APISIX等,具体使用哪种方式,需要根据场景进行选择。



参考资料:
http://openresty.org/cn
https://github.com/openresty/lua-resty-redis