Skip to content

Commit

Permalink
perf: Job 切换 GSE2.0 支持灰度策略 TencentBlueKing#2461
Browse files Browse the repository at this point in the history
  • Loading branch information
wangyu096 committed Sep 27, 2023
1 parent 1676845 commit 14f8f99
Show file tree
Hide file tree
Showing 41 changed files with 766 additions and 394 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@

package com.tencent.bk.job.common.service;

import com.tencent.bk.job.common.util.feature.FeatureToggle;
import com.tencent.bk.job.common.util.feature.FeatureStore;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
Expand All @@ -40,7 +41,12 @@
@Component
@Slf4j
public class ConfigRefreshEventListener {
public ConfigRefreshEventListener() {

private final FeatureStore featureStore;

@Autowired
public ConfigRefreshEventListener(FeatureStore featureStore) {
this.featureStore = featureStore;
log.info("Init ConfigRefreshEventListener");
}

Expand Down Expand Up @@ -76,7 +82,7 @@ private void reloadFeatureToggleIfChanged(Set<String> changedKeys) {
boolean isFeatureToggleConfigChanged =
changedKeys.stream().anyMatch(changedKey -> changedKey.startsWith("job.features."));
if (isFeatureToggleConfigChanged) {
FeatureToggle.reload();
featureStore.load(true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,21 @@
* IN THE SOFTWARE.
*/

package com.tencent.bk.job.common.util.feature.strategy;
package com.tencent.bk.job.common.service.feature;

import com.tencent.bk.job.common.service.config.ToggleStrategyConfig;
import lombok.Data;

@FunctionalInterface
public interface ToggleStrategyInitial {
ToggleStrategy build(ToggleStrategyConfig toggleStrategyConfig);
/**
* 特性配置
*/
@Data
public class FeatureConfig {
/**
* 是否启用特性
*/
private boolean enabled;
/**
* 特性启用策略;必须enabled=true,策略才会生效
*/
private ToggleStrategyConfig strategy;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available.
*
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
*
* BK-JOB蓝鲸智云作业平台 is licensed under the MIT License.
*
* License for BK-JOB蓝鲸智云作业平台:
* --------------------------------------------------------------------
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

package com.tencent.bk.job.common.service.feature;

/**
* 特性ID定义
*/
public interface FeatureIdConstants {
/**
* 特性: 对接 GSE2.0
*/
String FEATURE_GSE_V2 = "gseV2";
/**
* 特性: OpenAPI 兼容bk_biz_id参数
*/
String FEATURE_BK_BIZ_ID_COMPATIBLE = "bkBizIdCompatible";
/**
* 特性-第三方文件源
*/
String FEATURE_FILE_MANAGE = "fileManage";

/**
* 特性-是否支持GSE 获取文件分发任务结果的API协议(2.0版本之前)
*/
String GSE_FILE_PROTOCOL_BEFORE_V2 = "gseFileProtocolBeforeV2";
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* IN THE SOFTWARE.
*/

package com.tencent.bk.job.common.service.config;
package com.tencent.bk.job.common.service.feature;

import com.tencent.bk.job.common.util.json.JsonUtils;
import lombok.Getter;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/*
* Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available.
*
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
*
* BK-JOB蓝鲸智云作业平台 is licensed under the MIT License.
*
* License for BK-JOB蓝鲸智云作业平台:
* --------------------------------------------------------------------
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

package com.tencent.bk.job.common.service.feature;

import com.tencent.bk.job.common.service.feature.strategy.AllMatchToggleStrategy;
import com.tencent.bk.job.common.service.feature.strategy.AnyMatchToggleStrategy;
import com.tencent.bk.job.common.service.feature.strategy.FeatureConfigParseException;
import com.tencent.bk.job.common.service.feature.strategy.JobInstanceAttrToggleStrategy;
import com.tencent.bk.job.common.service.feature.strategy.ResourceScopeBlackListToggleStrategy;
import com.tencent.bk.job.common.service.feature.strategy.ResourceScopeWhiteListToggleStrategy;
import com.tencent.bk.job.common.service.feature.strategy.WeightToggleStrategy;
import com.tencent.bk.job.common.util.ApplicationContextRegister;
import com.tencent.bk.job.common.util.feature.Feature;
import com.tencent.bk.job.common.util.feature.FeatureStore;
import com.tencent.bk.job.common.util.feature.ToggleStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.helpers.MessageFormatter;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

/**
* 特性开关配置存储实现
*/
@Slf4j
public class InMemoryFeatureStore implements FeatureStore {

/**
* key: featureId; value: Feature
*/
private volatile Map<String, Feature> features = new HashMap<>();
/**
* 是否初始化
*/
private volatile boolean isInitial = false;

@Override
public Feature getFeature(String featureId) {
if (!isInitial) {
synchronized (this) {
if (!isInitial) {
load(false);
}
}
}
return features.get(featureId);
}

@Override
public void load(boolean ignoreException) {
synchronized (this) {
log.info("Load feature toggle start ...");
FeatureToggleConfig featureToggleConfig = ApplicationContextRegister.getBean(FeatureToggleConfig.class);

if (featureToggleConfig.getFeatures() == null || featureToggleConfig.getFeatures().isEmpty()) {
log.info("Feature toggle config empty!");
return;
}

Map<String, Feature> tmpFeatures = new HashMap<>();
featureToggleConfig.getFeatures().forEach((featureId, featureConfig) -> {
try {
Feature feature = parseFeatureConfig(featureId, featureConfig);
tmpFeatures.put(featureId, feature);
} catch (Throwable e) {
String msg = MessageFormatter.format(
"Load feature toggle config fail, skip update feature toggle config! featureId: {}, " +
"featureConfig: {}", featureId, featureConfig).getMessage();
log.error(msg, e);
if (features.get(featureId) != null) {
// 如果加载失败,那么使用原有的特性配置
tmpFeatures.put(featureId, features.get(featureId));
}
}
});

// 使用新的配置完全替换老的配置
features = tmpFeatures;
log.info("Load feature toggle config done! features: {}", features);
isInitial = true;
}
}

private Feature parseFeatureConfig(String featureId,
FeatureConfig featureConfig) throws FeatureConfigParseException {
if (StringUtils.isBlank(featureId)) {
log.error("FeatureId is blank");
throw new FeatureConfigParseException("FeatureId is blank");
}
Feature feature = new Feature();
feature.setId(featureId);
feature.setEnabled(featureConfig.isEnabled());

if (featureConfig.isEnabled()) {
ToggleStrategyConfig strategyConfig = featureConfig.getStrategy();
if (strategyConfig != null) {
ToggleStrategy toggleStrategy = parseToggleStrategy(strategyConfig);
if (toggleStrategy != null) {
feature.setStrategy(toggleStrategy);
}
}
}
return feature;
}

private ToggleStrategy parseToggleStrategy(ToggleStrategyConfig strategyConfig) {
String strategyId = strategyConfig.getId();
ToggleStrategy toggleStrategy;
switch (strategyId) {
case ResourceScopeWhiteListToggleStrategy.STRATEGY_ID:
toggleStrategy = new ResourceScopeWhiteListToggleStrategy(strategyConfig.getDescription(),
strategyConfig.getParams());
break;
case ResourceScopeBlackListToggleStrategy.STRATEGY_ID:
toggleStrategy = new ResourceScopeBlackListToggleStrategy(strategyConfig.getDescription(),
strategyConfig.getParams());
break;
case WeightToggleStrategy.STRATEGY_ID:
toggleStrategy = new WeightToggleStrategy(strategyConfig.getDescription(),
strategyConfig.getParams());
break;
case JobInstanceAttrToggleStrategy.STRATEGY_ID:
toggleStrategy = new JobInstanceAttrToggleStrategy(strategyConfig.getDescription(),
strategyConfig.getParams());
break;
case AllMatchToggleStrategy.STRATEGY_ID:
toggleStrategy = new AllMatchToggleStrategy(
strategyId,
strategyConfig.getStrategies()
.stream()
.map(this::parseToggleStrategy)
.collect(Collectors.toList()),
strategyConfig.getParams());
break;
case AnyMatchToggleStrategy.STRATEGY_ID:
toggleStrategy = new AnyMatchToggleStrategy(
strategyId,
strategyConfig.getStrategies()
.stream()
.map(this::parseToggleStrategy)
.collect(Collectors.toList()),
strategyConfig.getParams());
break;
default:
log.error("Unsupported toggle strategy: {} , ignore it!", strategyId);
throw new FeatureConfigParseException("Unsupported toggle strategy " + strategyId);
}
return toggleStrategy;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available.
*
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
*
* BK-JOB蓝鲸智云作业平台 is licensed under the MIT License.
*
* License for BK-JOB蓝鲸智云作业平台:
* --------------------------------------------------------------------
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

package com.tencent.bk.job.common.service.feature;

import lombok.Data;

import java.util.List;
import java.util.Map;

/**
* 特性启用策略配置
*/
@Data
public class ToggleStrategyConfig {
/**
* 策略ID
*/
private String id;
/**
* 策略说明
*/
private String description;
/**
* 组合策略
*/
private List<ToggleStrategyConfig> strategies;

/**
* 策略初始化参数
*/
private Map<String, String> params;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,28 @@
package com.tencent.bk.job.common.util.feature.strategy;
/*
* Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available.
*
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
*
* BK-JOB蓝鲸智云作业平台 is licensed under the MIT License.
*
* License for BK-JOB蓝鲸智云作业平台:
* --------------------------------------------------------------------
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

package com.tencent.bk.job.common.service.feature.strategy;

import com.tencent.bk.job.common.constant.ResourceScopeTypeEnum;
import com.tencent.bk.job.common.model.dto.ResourceScope;
Expand Down
Loading

0 comments on commit 14f8f99

Please sign in to comment.