用户维度的灰度方案

背景

在日常开发中,当修改了一些核心代码,或遇到测试环境难以完全覆盖的场景时,我们希望在上线时能通过灰度逐步放量来验证新逻辑。这样一来,如果发现问题,也可以快速切换回旧逻辑。

下面我就介绍下,一个简单的基于用户维度的灰度的方式。

整体流程

简单的流程如下:

处理逻辑:

接收到用户请求后,系统会根据用户标识和灰度配置规则进行处理,判断该用户是否被灰度。如果用户被灰度,则执行新的代码逻辑;如果未被灰度,则执行旧的代码逻辑。

灰度配置规则的存储

  1. 配置中心,使用的时候直接读取配置中心的配置,修改灰度的配置的时候,配置中心也可以快速的推到应用中,快速生效配置。
  2. 数据库+缓存,使用的时候从数据库中将配置加载到缓存中,读取缓存的灰度配置的数据,使用数据库+缓存的方式,修改灰度配置的时候要复杂一点,先去修改数据库里面的配置,再去删掉缓存中的数据。

灰度配置规则的处理

灰度配置处理逻辑

java 复制代码
     public boolean isGray(Long userId) {

        if (userId == null) {
            return false;
        }

        try {
		        // 灰度配置规则可以从 apollo 或者从缓存中取,根据实际情况 获取gray_config
            String rule = config.getProperty("gray_config", "");

            if (StringUtils.isEmpty(rule)) {
                return false;
            }

            JSONArray objects = JSON.parseArray(rule);

            if (CollectionUtils.isEmpty(objects)) {
                return false;
            }
            for (Object object : objects) {

                JSONObject jsonObject = (JSONObject) object;
                String type = jsonObject.getString("type");

                if (StringUtils.isEmpty(type)) {
                    continue;
                }

                if ("direct".equals(type)) {
                    String userIds = jsonObject.getString("data");
                    Set<String> userIdSet = StringUtils.commaDelimitedListToSet(userIds);
                    if (userIdSet.contains(String.valueof(userId))) {
                        return true;
                    }
                }

                if ("mod".equals(type)) {
                    Integer scale = jsonObject.getInteger("data");
                    if (scale < 0) {
                        continue;
                    }
                    if (scale >= 100) {
                        return true;
                    }

                    Integer remainder = (int) (userId % 100);
                    if (remainder <= scale) {
                        return true;
                    }
                }

            }
        }
        catch (Exception ex) {
            logger.error("处理灰度失败", ex);
        }
        return false;
    }

用户配置规则gray_config可以如下配置

java 复制代码
[
    {
        "type": "mod",
        "data": "10"
    },
    {
        "type": "direct",
        "data": "10001,10002"
    }
]

上述灰度配置表示的含义如下:

第一个配置:使用用户 ID 与 100(可自定义)取模。当取模后的值大于等于 0 且小于 10 时,表示该用户被灰度。如需扩大灰度范围,可以将 data 值调大,直到大于等于 100 时实现全量放开。当 data 值小于 0(如 -1)时,则为全量关闭。

第二个配置:将用户 ID 与指定的用户 ID 列表进行对比。如果用户 ID 存在于该列表中,则表示该用户被灰度;反之则未被灰度。

mod 和 direct 均可配置多条规则,只要满足其中任一规则,即视为通过灰度校验。

总结

以上介绍了一个简单的用户维度的灰度方案,可以灵活指定用户灰度或者按照比例对用户进行灰度。

这个用户比例计算也是一个大致的范围,可能有数据倾斜,不过总体还是能反应用户的分布的。

最后当灰度完成后,需要将旧代码删除。

相关推荐
大橙子打游戏11 小时前
OpenCode真的可以挑战Claude Code
后端
苏三说技术11 小时前
如何设计一个高并发系统?
后端
程序员鱼皮11 小时前
干掉 Claude Code,这个开源 AI 编程工具杀疯了?
前端·后端·计算机·ai·程序员
源代码•宸11 小时前
Golang基础语法(go语言结构体、go语言数组与切片、go语言条件句、go语言循环)
开发语言·经验分享·后端·算法·golang·go
数据小馒头12 小时前
MySQL文本处理:全库搜索慢?正则清洗难?掌握这 3 个方法
后端
星浩AI12 小时前
LCEL:打造可观测、可扩展、可部署的 LangChain 应用
人工智能·后端·python
数据小馒头12 小时前
MySQL并发与锁:从“防止超卖”到排查“死锁”
后端
用户2986985301412 小时前
C#: 在Word文档中添加或移除可编辑区域
后端·c#