【自研网关系列】过滤器链 -- 灰度发布过滤器

news2025/1/11 21:57:59

🌈Yu-Gateway:基于 Netty 构建的自研 API 网关,采用 Java 原生实现,整合 Nacos 作为注册配置中心。其设计目标是为微服务架构提供高性能、可扩展的统一入口和基础设施,承载请求路由、安全控制、流量治理等核心网关职能。

🌈项目代码地址:https://github.com/YYYUUU42/YuGateway-master

如果该项目对你有帮助,可以在 github 上点个 ⭐ 喔 🥰🥰

🌈自研网关系列:可以点开专栏,参看完整的文档

目录

1、什么是灰度发布

1.2、灰度发布关键特点和概念:

1.2、全链路灰度发布

2、网关层实现灰度发布


1、什么是灰度发布

灰度发布(Gray Release)是一种软件部署和发布策略,用于逐步将新版本的应用或服务引入生产环境,以降低潜在的风险并确保系统的稳定性。在灰度发布中,新版本的应用或服务不会一次性全部暴露给所有用户,而是逐渐引入一小部分用户,然后根据观察结果决定是否继续推广新版本或回滚到旧版本。这种策略有助于在生产环境中验证新功能、修复潜在问题以及逐渐接受用户反馈。

1.2、灰度发布关键特点和概念:

  • 渐进式发布:新版本逐渐替代旧版本,从一小部分用户开始,然后逐渐增加新版本的暴露范围。这可以是一个逐步增加百分比的用户,也可以是按照某种规则或条件选择的用户群体。
  • 风险控制:通过逐渐发布,可以在早期发现和解决潜在问题,从而减轻生产环境中可能发生的故障或问题对整体系统的影响。
  • 用户反馈:灰度发布过程中,可以收集用户的反馈和性能数据,帮助开发团队更好地了解新版本的行为和性能,以及用户的满意度。
  • 回滚能力:如果在灰度发布期间发现了严重问题或故障,可以轻松回滚到旧版本,从而减少对用户和业务的负面影响。
  • 分层策略:通常,灰度发布采用多层级策略,从开发环境到测试环境,再到生产环境,逐渐扩大发布的范围。这确保了新版本在不同环境中都经历了测试和验证。
  • 自动化工具:灰度发布通常借助自动化工具和部署管道来简化流程,例如使用容器编排工具、部署蓝绿或金丝雀发布等。

灰度发布是现代软件开发和交付的一种最佳实践,它允许组织更加安全和可控地推出新功能,降低风险,提高可维护性,同时减少对用户的影响。这是特别适用于大规模和高可用性系统的策略,以确保系统的连续性和稳定性。

1.2、全链路灰度发布

全链路发布是一种软件交付策略,它强调在整个软件开发和交付过程中的每个环节都进行逐步验证和控制,以确保新版本的成功发布并降低风险。全链路发布覆盖了整个软件生命周期,包括开发、测试、部署、监控、用户反馈和持续改进等阶段。

灰度发布注重的是部署发布这个过程,而全链路发布则范围更加广,包含了开发的整个生命周期,从开发,测试,到部署,维护等。

2、网关层实现灰度发布

知道了灰度发布的概念之后,就可以实现网关层面的灰度发布

在网关这里实现灰度发布,首先按照灰度发布的概念,只有部分用户会使用的就是灰度发布后的服务,因此,首先需要判断当前请求是否为灰度发布后的版本

在请求头设定 gray_release 字段,如果为 true 表示当前为一个灰度发布的版本

这样就可以在灰度发布过滤器中,将这个请求传递下去,并且在请求头中设定当前请求是否为灰度发布请求

代码层面就比较简单的,就是如果请求头中是为 true,就在 GatewayContext 中设置的 gray 属性为 ture,完整代码:

/**
 * @author yu
 * @description 灰度发布过滤器
 */
@FilterAspect(id = FilterConst.GRAY_FILTER_ID, name = FilterConst.GRAY_FILTER_NAME, order = FilterConst.GRAY_FILTER_ORDER)
public class GrayFilter implements Filter {
    private final Logger logger = LoggerFactory.getLogger(GrayFilter.class);
    private static String GRAY = "true";
    private static final int HASH_LENGTH = 1024;

    @Override
    public void doFilter(GatewayContext ctx) {
        if (ctx == null || ctx.getRequest() == null) {
            // 如果ctx或ctx.getRequest()为null,则直接返回,避免NullPointerException
            return;
        }

        String gray = ctx.getRequest().getHeaders().get(GRAY_FILTER_KEY);

        // 测试灰度功能待时候使用,可以手动指定其是否为灰度流量
        if (StringUtils.hasText(gray) && gray.equalsIgnoreCase(GRAY)) {
            logger.info("current user {} is set for grayService", ctx.getRequest().getClientIp());
            ctx.setGray(true);
            return;
        }

        // 选取部分灰度发布用户处理灰度流量
        String clientIp = ctx.getRequest().getClientIp();
        if (isValidClientIp(clientIp)) {
            // 使用取模运算改善边界条件
            int res = clientIp.hashCode() % HASH_LENGTH;
            if (res == 1) {
                logger.info("current client {} is selected for grayService", clientIp);
                ctx.setGray(true);
            }
        }
    }

    /**
     * 验证clientIp是否是有效的
     */
    private boolean isValidClientIp(String clientIp) {
        // 正则表达式,用于验证IPv4地址的格式
        String ipv4Pattern = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
        // 正则表达式,用于验证IPv6地址的格式
        String ipv6Pattern = "^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$";

        // 如果clientIp为null或者为空,那么就返回false
        if (clientIp == null || clientIp.isEmpty()) {
            return false;
        }

        // 如果clientIp匹配IPv4或IPv6的正则表达式,那么就返回true,否则返回false
        return clientIp.matches(ipv4Pattern) || clientIp.matches(ipv6Pattern);
    }
}

这里主要就是根据服务id那里得到服务的实例,如果是请求头如果是true的话,就只会从服务实例中gray中为true的,如果服务实例中没有true的,就会报错

/**
 * 根据服务ID获取服务实例
 */
public Set<ServiceInstance> getServiceInstanceByUniqueId(String uniqueId, boolean gray) {
    Set<ServiceInstance> instanceSet = serviceInstanceMap.get(uniqueId);
    if (CollectionUtils.isEmpty(instanceSet)) {
        return Collections.EMPTY_SET;
    }
    // 为灰度流量,返回灰度服务实例
    if (gray) {
        return instanceSet.stream().filter(ServiceInstance::isGray).collect(Collectors.toSet());
    }
    return instanceSet;
}

这个的话可以在 nacos 上修改,或者在请求接口中配置文件中修改

server:
  port: 8201

api:
  registerAddress: 127.0.0.1:8848
  env: dev
  gray: true

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1635818.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图像预处理工具_CogImageFileTool

CogImageFileTool工具可以用来将单张图片或idb格式的图片数据库读入内存。也可使用CoglmageFileTool工具将图片插入到.idb数据库里。 添加工具 参数介绍 文件名 写入模式 读取模式 删除

k8s集群Grafana精选dashboard页面

文章目录 参考文档 Grafana自选模板推荐模板&#xff1a;13332、13824、14518Grafana默认配置我们选择 Node Exporter/Nodes 的 Dashboard 进去&#xff1a;点击 Kubernetes/Networking/Cluster 进去使用模板查看结果 Grafana接入Prometheus数据Grafana添加监控模板导入 1860_r…

Hotcoin Research|玩赚WEB3:Seraph零成本赚取技巧

在《Seraph》这款游戏里&#xff0c;要提升自己的游戏技能和体验&#xff0c;了解如何免费赚取游戏货币灵魂晶石并挑战游戏主线是非常重要的。你可以通过卖东西、参加虚空异界地图和混沌秘境来在游戏里赚更多的钱&#xff0c;并更享受游戏的乐趣。最酷的是&#xff0c;得到的灵…

远程桌面连接服务器怎样连接不上的六个常见原因

远程桌面连接服务器无法连接的问题可能由多种原因引起。以下是一些常见的问题及其解决方案&#xff1a; 1. 网络连接问题&#xff1a;远程桌面连接的基础是稳定的网络连接。如果网络连接不稳定或中断&#xff0c;那么你将无法连接到远程桌面。检查你的网络连接&#xff0c;确保…

ubuntu 利用阿里网盘API实现文件的上传和下载

文章目录 背景脚本初始化 阿里云盘API工具 aligo安装aligoaligo教程实战parse.py 演示上传文件上传文件夹下载文件下载文件夹 背景 最近在用ubuntu系统做实验&#xff0c;而ubuntu 系统的文件上传和下载操作很麻烦&#xff1b; 于是便打算使用阿里网盘的API 进行文件下载与上传…

局域网屏幕桌面监控哪个软件比较好?哪款好用?

在企业、教育机构或其他组织中&#xff0c;出于提高工作效率、保障数据安全、规范员工行为等目的&#xff0c;对局域网内电脑屏幕进行实时监控的需求日益凸显。 面对市场上众多屏幕监控软件&#xff0c;选择一款功能全面、稳定可靠且符合法规要求的产品至关重要。 在局域网屏幕…

git revert的使用

由于某种原因我们需要撤销掉之前某一次的修改&#xff0c;但是这个修改已经提交&#xff0c;并且后面又经历了好几轮的提交。可能如下这种情况&#xff1a; 那么此时使用git revert再合适不过啦。git revert ${commit_id}就可以将指定commit id的修改撤销&#xff0c;然后提交…

STM32入门_江协科技_3~4_OB记录的自学笔记_软件安装新建工程

3. 软件安装 3.1. 安装Keil5 MDK 作者的资料下载的连接如下&#xff1a;https://jiangxiekeji.com/download.html#32 3.2. 安装器件支持包 因为新的芯片层出不穷&#xff0c;所以需要安装Keil5提供的器件升级版对软件进行升级&#xff0c;从而支持新的芯片&#xff1b;如果不…

Vue入门到关门之组件

一、组件 1、什么是组件 在Vue.js中&#xff0c;组件是构建用户界面的可重用和独立的模块。每个Vue组件都封装了自己的模板、逻辑和样式&#xff0c;使得代码可以更加模块化、可维护性更高。通过组件化&#xff0c;你可以将界面拆分成独立的、可复用的部分&#xff0c;每个部…

linux dma的使用

设备树配置 驱动代码 static void bcm2835_dma_init(struct spi_master *master, struct device *dev) { struct dma_slave_config slave_config; const __be32 *addr; dma_addr_t dma_reg_base; int ret; /* base address in dma-space */ addr of_get_address(master->de…

visionPro链接相机

搜索Cognex GigE Vision Configura… 修改子网掩码为255.255.255.0 配置驱动程序 更新驱动&#xff08;如果能够选择9014Bytes&#xff0c;跳过此步骤&#xff09; 更新更改 相机ip配置 打开visionPro 选择照相机 查看实时画面 运行保存图像

【C++】哈希表的底层逻辑

目录 一、哈希概念 1、哈希冲突 2、哈希冲突的解决 a、闭散列 &#x1f7e2;插入 &#x1f7e2;查找 &#x1f7e2;删除 &#x1f7e2;其他类型的数据 &#x1f7e2;实现 b、 开散列 &#x1f7e2;插入 &#x1f7e2;查找 &#x1f7e2;删除 &#x1f7e2;析构 &a…

RTMP 直播推流 Demo(一)—— 项目配置与视频预览

音视频编解码系列目录&#xff1a; Android 音视频基础知识 Android 音视频播放器 Demo&#xff08;一&#xff09;—— 视频解码与渲染 Android 音视频播放器 Demo&#xff08;二&#xff09;—— 音频解码与音视频同步 RTMP 直播推流 Demo&#xff08;一&#xff09;—— 项目…

ASR语音转录Prompt优化

ASR语音转录Prompt优化 一、前言 在ASR转录的时候&#xff0c;我们能很明显的感受到有时候语音识别不是很准确&#xff0c;这过程中常见的文本错误主要可以归纳为以下几类&#xff1a; 同音错误&#xff08;Homophone Errors&#xff09; 同音错误发生在不同词语发音相似或相…

javafx如何一键打包成exe

javafx如何打包成exe JavaFX-Template-Native 集成jfoenix、commons-math、commons-lang3、netty&#xff0c;方便一些和底层做通信使用&#xff0c;不需要可以自行pom中去掉依赖当前使用的jdk17&#xff0c;理论上jdk14都支持采用模块化&#xff0c;支持一键打包生成很小的ex…

远程桌面的端口配置与优化

在现代企业环境中&#xff0c;远程桌面连接已成为日常工作中不可或缺的一部分。然而&#xff0c;随着网络攻击的增加&#xff0c;确保远程桌面连接的安全性变得尤为重要。其中一个关键的安全因素是端口配置。 一、远程桌面默认端口 远程桌面协议&#xff08;RDP&#xff09;默…

深度学习之视觉特征提取器——LeNet

LeNet 引入 LeNet是是由深度学习巨头Yann LeCun在1998年提出&#xff0c;可以算作多层卷积网络在图像识别领域的首次成功应用。我们现在通常说的LeNet是指LeNet-5&#xff0c;最早的LeNet-1在1988年即开始研究&#xff0c;前后持续十年之久。但是&#xff0c;受限于当时计算机…

关于远程桌面与3389端口的深度解析

当我们谈论远程桌面和3389端口时&#xff0c;我们实际上是在探讨Windows操作系统的一个核心功能&#xff0c;该功能允许用户通过网络从任何地点远程控制和管理计算机。而3389端口&#xff0c;正是这一功能所依赖的通信端口。 一、远程桌面的工作原理 远程桌面协议&#xff08;R…

C++---重载

1、运算符重载 #include <iostream> using namespace std; class complex { int rel; int vir; public: complex(){} complex(int rel,int vir):rel(rel),vir(vir){} void show() { cout << rel << "" << vir << "i" <&l…

nodejs写接口(一)

一、新手上路十大步 &#xff08;1&#xff09;先建一个常用的文件夹 &#xff08;2&#xff09;使用code打开 &#xff08;3&#xff09;在里面新建一个index.js文件 &#xff08;4&#xff09;新建项目 npm init -y //用于自己搭建一个项目框架&#xff08;写框架&#xf…