基于WebFilter实现断言和转发的灰度流量控制方案

本文介绍了如何在Java项目中通过WebFilter实现部分流量路由到Go项目,采用灰度策略逐步迁移核心链路。涉及到了过滤器的选择、灰度规则判断、请求解析和转发模块的设计,以及灰度配置的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于WebFilter实现断言和转发的灰度流量控制方案

1、需求背景

响应Java转Go的趋势,在部分服务已经转Go的情况下,需要把部分打到原Java项目的流量路由到Go项目上。

1.1、为什么是部分流量而不是全部?

因为涉及到的项目是交易核心链路,这也是灰度的重要作用。在进行核心链路的重构替代的时候,必须使用灰度方案,逐步进行迁移。落实到具体操作就是,前期只对小商家、非核心商家的流量路由到Go,确保Go项目没问题再逐步提高灰度的比例。一个好的需求要实现可灰度、可回滚、可监控。

1.2、为什么在服务层做过滤而不是网关?

因为成本原因,网关会逐步下线。目前灰度流量控制方案选择用SDK的方式来实现。假如在网关层做流量控制,被灰度的流量就不会进入到Java项目,Java项目的流量承担会少一点,但是也需要结合网关服务的成本综合考虑。


2、流程图

在这里插入图片描述

一些细节:

1、请求的拦截用过滤器而不是拦截器。因为服务中存在别的拦截器或者过滤器,而过滤器会比拦截器先拦截到请求,因此就会减少被路由到Go服务的请求对Java服务的资源的消耗;

2、在根据ChannelID和MerchantID判断是否需要灰度的时候,需要做成只依赖这两个ID和灰度配置去判断,而不要传递整个Servlet在内部做解析。


3、断言模块设计

请求进入到拦截器的第一个部分,需要在这个部分判断是否需要进行灰度。具体的操作为尝试获取目标接口的目标配置,假如获取不到则不参与灰度,假如能够获取到则参参与灰度。

配置的存储结构为Map<接口-配置>,但是假如url是可变的,也就是参数存在于路径上就会出现匹配不到的情况,比如说/config/1和/config/2,虽然都是请求同一个接口,但是由于参数不同,从httpservlet中拿到的uri也会不同,所以没有办法存放。

所以具体设计如下,Map中存放的为<接口/正则表达式-配置>。固定接口就直接存放接口,可变接口就存放正则表达式,如"/getJavaToGoGrayConfigJson/\d+"。

取的时候优先使用精确匹配,假如匹配不到的话再遍历Map的key,尝试进行正则匹配。

private GrayConfig getConfig(String uri) {
   
    if (GRAY_CONFIG.isEmpty() || this.isConfigExpired()) {
   
        // 更新配置信息
        try {
   
            this.refreshConfig();
        }catch (Exception e){
   
            log.error("GoGrayRouteFilter refreshConfig fail"+e);
        }
    }
    GrayConfig grayConfig = GRAY_CONFIG.get(uri);
    if (grayConfig == null) {
   
        for (Map.Entry<String, GrayConfig> grayConfigEntry : GRAY_CONFIG.entrySet()) {
   
            // 前缀匹配,然后进行正则匹配
            String regex = grayConfigEntry.getValue().getUri();
            Pattern pattern = Pattern.compile(regex);
            // 创建 Matcher 对象并进行匹配
            Matcher matcher = pattern.matcher(uri);

            // 判断是否匹配成功
            if (matcher.matches()) {
   
                grayConfig = grayConfigEntry.getValue();
                System.out.println("judge gray 匹配成功!");
                return grayConfig;
            } else {
   
                System.out.println("judge gray 匹配失败!");
            }
        }
    }
    return grayConfig;
}
3.1、优化

遍历Map的Key显然不太明智,这里提供了一些优化方案。

1、同时维护一个List,存放Key,遍历的时候遍历这个List;

2、缓存设计,缓存可变接口的请求到Map,下次再请求就可以精确匹配;

3、维护一棵前缀树,通过前缀树进行查找而不是遍历。


4、请求解析模块设计

拿到灰度配置之后,需要根据灰度配置解析请求中的数据,再根据这些数据判断需不需要灰度。请求的数据会存放在三个地方:url、查询参数、请求体。我们需要根据配置从不同的位置拿到请求。

4.1、url

url参数的情况比较多样,可以通过正则表达式来处理。这里需要用到命名组的概念,举个例子,有这么一条请求"/test/1/2",1对应用变量id1

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值