Java按百分比切分流量

由于博客内容为空,暂无法提供包含关键信息的摘要。

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

package com.hang.demo;

import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Percent {

    private static volatile List<String> list1 = new ArrayList<>();

    private static volatile List<String> list2 = new ArrayList<>();

    private static volatile List<String> list3 = new ArrayList<>();

    public static void main(String[] args) {

        Long tid = 1324684169472136L;

        Long pid = 132468416546345L;

        Long sid = 1324684169473147L;

        String[] groups = new String[] {"1A", "1B", "1C"};

        double[] rates = new double[] {10.0, 30.0, 60.0};

        for (int i = 0; i < 1000; i++) {
            String group_super_id = choose(tid + "-" + pid + "-" + sid + "" + i, groups, rates);
            if (group_super_id.endsWith("1A")) {
                list1.add(group_super_id);
            } else if (group_super_id.endsWith("1B")) {
                list2.add(group_super_id);
            } else if (group_super_id.endsWith("1C")) {
                list3.add(group_super_id);
            }
        }
        System.out.println(list1.size() + "---" + list2.size() + "---" + list3.size());
    }

    /**
     * 流量切分算法(随机)
     *
     * @param superId 用户id
     * @param strategyId 策略id
     * @param groups 对照组
     * @param rates 对照组百分比
     * @return 分组
     */
    public static String choose(Long superId, Long strategyId, String [] groups, double[] rates) {
        if (null == groups || 0 == groups.length || null == rates || 0 == rates.length) {
            return null;
        }

        String id = strategyId + "" + superId;

        String digest = DigestUtils.md5DigestAsHex(id.getBytes());
        int hashCode = digest.hashCode();
        int random = Math.abs(hashCode) % 100;

        double start = 1.0;
        double end = 0.0;

        // 最多只有5个对照组
        for (int i = 0; i < rates.length; i++) {
            end = end + rates[i];
            if (start <= random && random <= end) {
                String group = groups[i];
                if (group.equals(groups[0])) {
                    logger.info("ABTestServiceImpl.choose [super_id]: {}", superId + "-" + group);
                    return group;
                } else if (group.equals(groups[1])) {
                    logger.info("ABTestServiceImpl.choose [super_id]: {}", superId + "-" + group);
                    return group;
                } else if (group.equals(groups[2])) {
                    logger.info("ABTestServiceImpl.choose [super_id]: {}", superId + "-" + group);
                    return group;
                } else if (group.equals(groups[3])) {
                    logger.info("ABTestServiceImpl.choose [super_id]: {}", superId + "-" + group);
                    return group;
                } else if (group.equals(groups[4])) {
                    logger.info("ABTestServiceImpl.choose [super_id]: {}", superId + "-" + group);
                    return group;
                }
            }
            start = start + rates[i];
        }
        return null;
    }

}

### Zuul 迁移至 Spring Cloud Gateway 的并存与换最佳实践及部署方案 #### 1. 并存阶段的设计 在迁移初期,通常会采用新旧网关共存的方式以降低风险。这种模式允许两个网关同时运行一段时间,在此期间可以逐步将流量从 Zuul 换到 Spring Cloud Gateway[^1]。 - **负载均衡器配置**:通过外部负载均衡器(如 Nginx 或 ALB)分配流量给 Zuul 和 Spring Cloud Gateway。可以根据权重或其他条件控制两者的比例。 - **统一入口设计**:如果可能的话,让两种网关共享同一个域名并通过路径区分请求流向。例如: - `/zuul/**` 路由到 Zuul; - `/gateway/**` 路由到 Spring Cloud Gateway。 ```nginx server { listen 80; server_name example.com; location /zuul/ { proxy_pass http://zuul-cluster/; } location /gateway/ { proxy_pass http://spring-cloud-gateway-cluster/; } } ``` #### 2. 流量切分策略 为了平稳过渡,需制定合理的流量割计划。以下是几种常见方法: - **基于百分比的灰度发布**:利用 Spring Cloud Gateway 提供的功能,按照一定比例划分流导向目标服务的不同版本[^4]。如下所示,可根据请求头中的字段决定具体走向哪个实例群组。 ```yaml spring: cloud: gateway: routes: - id: zuul_fallback_route uri: lb://zuul-service predicates: - Path=/api/** - id: gateway_new_feature_route uri: lb://new-feature-service predicates: - Header=x-version, v2 filters: - StripPrefix=1 ``` - **用户群体隔离测试**:选取一小批内部员工或特定地区的客户作为试点对象参与早期体验活动。一旦发现问题即可快速回滚而不至于影响全局用户体验。 #### 3. 数据一致性保障 由于存在双写现象即同一份数据可能会被先后提交至两个独立系统之中因此必须特别关注事务管理和同步逻辑方面的工作确保最终状态一致无误[^2]。 - 实现幂等接口减少重复操作引发冲突的可能性。 - 对于跨数据库之间的关联关系建立补偿机制以便失败情况下能够恢复原状。 #### 4. 监控报警体系完善 在整个迁移过程中持续跟踪各项指标表现至关重要包括但不限于响应时间成功率错误码分布等等任何异常波动都可能是潜在隐患所在之处需要立即调查原因加以修正直至恢复正常水平为止[^3]。 --- ### 示例代码片段展示如何动态调整路由规则 下面提供了一段关于如何编程修改现有 RouteDefinition 的例子它展示了灵活操控能力使得我们可以很容易地适应不断变化的需求环境当中去。 ```java @Service public class DynamicRouteService { @Autowired private RouteDefinitionWriter routeDefinitionWriter; public void addNewRoute(String id, String uriStr){ RouteDefinition definition = new RouteDefinition(); definition.setId(id); URI uri = UriComponentsBuilder.fromUriString(uriStr).build().toUri(); definition.setUri(uri); List<PredicateDefinition> predicateList = new ArrayList<>(); PredicateDefinition predicate = new PredicateDefinition(); predicate.setName("Path"); Map<String, String> args = new HashMap<>(); args.put("pattern", "/"+id+"/**"); predicate.setArgs(args); predicateList.add(predicate); definition.setPredicates(predicateList); this.routeDefinitionWriter.save(Mono.just(definition)).subscribe(); } } ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值