abtest灰度、多版本发布核心算法

76 阅读1分钟

前言

下面是abtest进行流量分流和保证用户粘性的核心算法代码demo,生产中还需要考虑到指标收集、落库、缓存提高并发,保证高并发高可用高效率。

如果需要集成到网关服务springcloud gateway,请结合我的另一篇文章

blog.csdn.net/qq_41214487…

首先依旧采用ketemaHash算法,替代默认的hashcode方法,实现分布更加均匀的hash算法:

public class KetamaHash {
    private static MessageDigest md5Digest;
    static {
        try {
            md5Digest = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException var1) {
            throw new RuntimeException("MD5 not supported", var1);
        }
    }
    public int getHash(String origin) {
        byte[] bKey = computeMd5(origin);
        long rv = (long)(bKey[3] & 255) << 24 | (long)(bKey[2] & 255) << 16 | (long)(bKey[1] & 255) << 8 | (long)(bKey[0] & 255);
        return (int)(rv & 4294967295L);
    }

    private static byte[] computeMd5(String k) {
        MessageDigest md5;
        try {
            md5 = (MessageDigest)md5Digest.clone();
        } catch (CloneNotSupportedException var3) {
            throw new RuntimeException("clone of MD5 not supported", var3);
        }

        md5.update(k.getBytes());
        return md5.digest();
    }
}

一个比较简单的ab路由算法

    private static String calculation( GroupDto group,String info){

        KetamaHash ketamaHash = new KetamaHash();
        BigDecimal a = group.getAPercentage().multiply(BigDecimal.TEN);
        BigDecimal b = group.getBPercentage().multiply(BigDecimal.TEN);
        BigDecimal z = group.getZPercentage().multiply(BigDecimal.TEN);

        BigDecimal total = a.add(b).add(z);
         int hasCode = Math.abs(ketamaHash.getHash(info));
        double v = hasCode % total.doubleValue();

        BigDecimal vb = new BigDecimal(v);

        if (vb.compareTo(a) < 0){
            return "A";
        }else if (vb.compareTo(a.add(b)) < 0){
            return "B";
        }else {
            return "Z";
        }

}

最后进行测试

    public static void main(String[] args) {
        long l = System.currentTimeMillis();
        KetamaHash ketamaHash = new KetamaHash();
        GroupDto groupDto = new GroupDto(BigDecimal.valueOf(0.5),BigDecimal.valueOf(0.3),BigDecimal.valueOf(0.2));
        List list = new ArrayList();
        for (int i = 0; i < 10000; i++) {
            String s = calculation(groupDto, "hello"+Math.random());
            list.add(s);
            System.out.println(i+":"+s);
        }
        long l1 = System.currentTimeMillis();
        System.out.println(l1-l);
        int a = countLetters(list, "A");
        int b = countLetters(list, "B");
        int z = countLetters(list, "Z");
        System.out.println("A出现了:"+a+"次");
        System.out.println("B出现了:"+b+"次");
        System.out.println("Z出现了:"+z+"次");

    }
    public static int countLetters(List list,String info ) {
        int counts=0;
        for(int i=0;i<list.size();i++)
        {
            if (list.get(i).equals(info))
            {
                counts++;
            }
        }
        return counts;
    }

结果 在这里插入图片描述