灰度工具
前言
Github:https://github.com/HealerJean
一、灰度枚举 GrayEnum
package com.hlj.util.z028_灰度工具;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* GrayEnum
* @author zhangyujin1
* @date 2021/4/14 2:24 下午.
*/
public interface GrayEnum {
/**
* 灰度进度
*/
@Getter
@AllArgsConstructor
enum GrayResEnum implements GrayEnum {
/**
* GRAY_CLOSE
*/
GRAY_WHITE_TRUE( "whiteHit", true,"命中灰度白名单"),
GRAY_TRUE("hit" ,true,"命中灰度"),
GRAY_CLOSE( "close", false,"灰度关闭"),
GRAY_NOT_EXIST( "notExist", false,"灰度不存在"),
GRAY_BLACK_TRUE( "blackHit", false,"命中灰度白名单"),
GRAY_FALSE("unHit", false, "未命中或者灰度不存在"),
;
/**
* 灰度详细结果
*/
private final String code;
/**
* 灰度结果
*/
private final Boolean flag;
/**
* desc
*/
private final String desc;
}
/**
* 灰度业务
*/
@Getter
@AllArgsConstructor
enum GrayBusinessEnum implements GrayEnum {
/**
* INSURANCE_6067
*/
BUSINESS_OOO1("businessDemo", "灰度场景1"),
;
/**
* insuranceId
*/
private final String bizType;
/**
* desc
*/
private final String bizDesc;
/**
* GrayBusinessEnum
* @param bizType insuranceId
* @return GrayBusinessEnum
*/
public static GrayBusinessEnum toGrayBusinessEnum(String bizType) {
return Arrays.stream(GrayBusinessEnum.values()).filter(item->item.getBizType().equals(bizType)).findAny().orElse(null);
}
}
}
二、灰度配置
依靠配置中心进行配置
package com.hlj.util.z028_灰度工具;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
/**
* DuccBypassInsuranceConfiguration
*
* @author zhangyujin
* @date 2022/9/21 21:21.
*/
@Slf4j
@Data
@Configuration
public class GrayConfiguration {
/**
* 灰度对象
*/
private Map<String, GrayBizBO> grayBizMap;
}
package com.hlj.util.z028_灰度工具;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Set;
/**
* GrayInsuranceBusinessDto
* @author zhangyujin
* @date 2022/9/22 13:48.
*/
@Accessors(chain = true)
@Data
public class GrayBizBO implements Serializable {
/**
* serialVersionUID
*/
private static final long serialVersionUID = 5110796299306482078L;
/**
* 灰度开关
*/
private Boolean flag;
/**
* 灰度白名单
*/
private Set<String> whiteInfos;
/**
* 灰度黑名单
*/
private Set<String> blackInfos;
/**
* 灰度比例
*/
private Integer rate;
/**
* 灰度总额
*/
private Integer amount;
}
三、灰度工具
package com.hlj.util.z028_灰度工具;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
* 自制工具类
*
* @author healerjean
* @date 2022-09-21 22:27
*/
@Service
@Slf4j
public class GrayUtil {
/**
* grayConfiguration
*/
private static final GrayConfiguration grayConfiguration;
static {
grayConfiguration = new GrayConfiguration();
Map<String, GrayBizBO> grayBizMap = Maps.newHashMap();
grayBizMap.put(GrayEnum.GrayBusinessEnum.BUSINESS_OOO1.getBizType(),
new GrayBizBO()
.setFlag(true)
.setRate(2)
.setAmount(10)
.setWhiteInfos(Sets.newHashSet("4", "5", "6"))
.setBlackInfos(Sets.newHashSet("7", "8", "9")));
grayConfiguration.setGrayBizMap(grayBizMap);
}
/**
* 是否命中灰度
* 一、灰度业务判断
* 1、灰度业务不存在 返回:GrayEnum.GrayResEnum.GRAY_NOT_EXIST
* 2、判断是否灰度关闭,是返回 GrayEnum.GrayResEnum.GRAY_CLOSE;
* 二、灰度黑白名单判断
*
* @param grayBusinessEnum 灰度业务枚举
* @param grayValue 灰度值
* @return 灰度开关是否打开
*/
public static GrayEnum.GrayResEnum hitGray(GrayEnum.GrayBusinessEnum grayBusinessEnum, String grayValue) {
// 一、灰度业务判断
// 1、灰度业务不存在 返回:GrayEnum.GrayResEnum.GRAY_NOT_EXIST
Map<String, GrayBizBO> grayBizMap = Optional.ofNullable(grayConfiguration.getGrayBizMap()).orElse(Maps.newHashMap());
GrayBizBO grayBiz = grayBizMap.get(grayBusinessEnum.getBizType());
if (Objects.isNull(grayBiz)) {
log.info("[GrayUtil#hitGray] grayBusinessEnum:{}, grayValue:{} 灰度结果: false(未配置灰度)", grayBusinessEnum, grayValue);
return GrayEnum.GrayResEnum.GRAY_NOT_EXIST;
}
// 2、判断是否灰度关闭,是返回 GrayEnum.GrayResEnum.GRAY_CLOSE;
if (Boolean.FALSE.equals(grayBiz.getFlag())) {
log.info("[GrayUtil#hitGray] grayBusinessEnum:{}, grayValue:{} 灰度结果: false(灰度关闭)", grayBusinessEnum, grayValue);
return GrayEnum.GrayResEnum.GRAY_CLOSE;
}
// 二、灰度黑白名单判断
// 1、白名单判断,如果在白名单,返回:GrayEnum.GrayResEnum.GRAY_WHITE_TRUE;
Set<String> whiteUsers = Optional.ofNullable(grayBiz.getWhiteInfos()).orElse(Sets.newHashSet());
if (whiteUsers.contains(grayValue)) {
log.info("[GrayUtil#hitGray] grayBusinessEnum:{}, grayValue:{} 灰度结果:true(白名单命中)", grayBusinessEnum, grayValue);
return GrayEnum.GrayResEnum.GRAY_WHITE_TRUE;
}
// 2、黑白名单判断,如果在白名单,返回:GrayEnum.GrayResEnum.GRAY_BLACK_TRUE;
Set<String> blackInfos = Optional.ofNullable(grayBiz.getBlackInfos()).orElse(Sets.newHashSet());
if (blackInfos.contains(grayValue)) {
log.info("[GrayUtil#hitGray] grayBusinessEnum:{}, grayValue:{} 灰度结果:false(黑名单命中)", grayBusinessEnum, grayValue);
return GrayEnum.GrayResEnum.GRAY_BLACK_TRUE;
}
// 三、灰度比例判断
// 3.1、灰度比例不存在,则返回false
Integer grayPercent = grayBiz.getRate();
Integer grayPercentAmount = grayBiz.getAmount();
// 3.2、灰度比例计算,命中返回ture,不命中返回false
int rate = Math.abs(hashValue(grayBusinessEnum, grayValue)) % grayPercentAmount;
if (rate <= grayPercent) {
log.info("[GrayUtil#hitGray] grayBusinessEnum:{}, grayValue:{} 灰度结果:true(灰度命中)", grayBusinessEnum, grayValue);
return GrayEnum.GrayResEnum.GRAY_TRUE;
}
log.info("[GrayUtil#hitGray] grayBusinessEnum:{}, grayValue:{} 灰度结果:false(灰度未命中)", grayBusinessEnum, grayValue);
return GrayEnum.GrayResEnum.GRAY_FALSE;
}
/**
* hashValue
*
* @param grayBusinessEnum grayBusinessEnum
* @param grayValue grayValue
* @return {@link Integer}
*/
public static Integer hashValue(GrayEnum.GrayBusinessEnum grayBusinessEnum, String grayValue) {
return Integer.valueOf(grayValue);
}
@Test
public void test(){
System.out.println(hitGray(GrayEnum.GrayBusinessEnum.BUSINESS_OOO1, "1"));
System.out.println(hitGray(GrayEnum.GrayBusinessEnum.BUSINESS_OOO1, "2"));
System.out.println(hitGray(GrayEnum.GrayBusinessEnum.BUSINESS_OOO1, "3"));
System.out.println(hitGray(GrayEnum.GrayBusinessEnum.BUSINESS_OOO1, "4"));
System.out.println(hitGray(GrayEnum.GrayBusinessEnum.BUSINESS_OOO1, "5"));
System.out.println(hitGray(GrayEnum.GrayBusinessEnum.BUSINESS_OOO1, "6"));
System.out.println(hitGray(GrayEnum.GrayBusinessEnum.BUSINESS_OOO1, "7"));
System.out.println(hitGray(GrayEnum.GrayBusinessEnum.BUSINESS_OOO1, "8"));
System.out.println(hitGray(GrayEnum.GrayBusinessEnum.BUSINESS_OOO1, "9"));
}
}