灰度工具
前言
Github:https://github.com/HealerJean
一、灰度枚举 GrayEnum
public interface GrayEnum {
/**
* 灰度进度
*/
@Getter
@AllArgsConstructor
enum GrayResEnum implements GrayEnum {
/**
* GRAY_CLOSE
*/
GRAY_WHITE_TRUE( "whiteHit", true,"命中灰度白名单"),
GRAY_TRUE("hit" ,true,"命中灰度"),
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"),
;
/**
* code
*/
private final String code;
/**
* desc
*/
private final String desc;
/**
* GrayBusinessEnum
* @param code code
* @return GrayBusinessEnum
*/
public static GrayBusinessEnum toGrayBusinessEnum(String code) {
return Arrays.stream(GrayBusinessEnum.values()).filter(item->item.getCode().equals(code)).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;
}
三、灰度工具
@Slf4j
public class GrayUtil {
/**
* 是否命中灰度
* 一、灰度业务判断
* 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) {
// 一、灰度业务判断 返回:GrayEnum.GrayResEnum.GRAY_NOT_EXIST
GrayConfiguration grayConfiguration = SpringUtils.getBean(GrayConfiguration.class);
Map<String, GrayBizBO> grayBizMap = Optional.ofNullable(grayConfiguration.getGrayBizMap()).orElse(Maps.newHashMap());
GrayBizBO grayBiz = grayBizMap.get(grayBusinessEnum.getCode());
if (Objects.isNull(grayBiz)) {
log.info("[GrayUtil#hitGray] grayBusinessEnum:{}, grayValue:{} 灰度结果: false(未配置灰度)", grayBusinessEnum, grayValue);
return GrayEnum.GrayResEnum.GRAY_NOT_EXIST;
}
// 二、灰度黑白名单判断
// 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
long grayPercent = grayBiz.getRate();
long grayPercentAmount = grayBiz.getAmount();
// 3.2、灰度比例计算,命中返回ture,不命中返回false
long 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}
*/
private static Long hashValue(GrayEnum.GrayBusinessEnum grayBusinessEnum, String grayValue) {
return Long.valueOf(grayValue);
}
}