From 4034f4821334212bad4c4e60ff426f7ace0bd875 Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Mon, 2 Sep 2024 18:26:01 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E8=8A=82=E7=82=B9=E8=BD=AE=E8=AF=A2=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: fit2-zhao --- .../api/jmeter/utils/SmoothWeighted.java | 116 ++++++++++-------- 1 file changed, 63 insertions(+), 53 deletions(-) diff --git a/api-test/backend/src/main/java/io/metersphere/api/jmeter/utils/SmoothWeighted.java b/api-test/backend/src/main/java/io/metersphere/api/jmeter/utils/SmoothWeighted.java index 9315884696..aba921d0f1 100644 --- a/api-test/backend/src/main/java/io/metersphere/api/jmeter/utils/SmoothWeighted.java +++ b/api-test/backend/src/main/java/io/metersphere/api/jmeter/utils/SmoothWeighted.java @@ -1,6 +1,5 @@ package io.metersphere.api.jmeter.utils; - import io.metersphere.base.domain.TestResource; import io.metersphere.commons.utils.GenerateHashTreeUtil; import io.metersphere.commons.utils.JSON; @@ -12,102 +11,115 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.data.redis.core.RedisTemplate; import java.util.*; +import java.util.stream.Collectors; /** * 平滑加权轮询算法 */ public class SmoothWeighted { - private static final String BASE_URL = "http://%s:%d"; + public static final String BASE_URL = "http://%s:%d"; public static final String CONFIG = "CONFIG_"; public static final String EXEC_INDEX = "EXEC_INDEX_"; - public static void setServerConfig(String poolId, RedisTemplate client) { + public static void setServerConfig(String poolId, RedisTemplate client) { if (StringUtils.isEmpty(poolId)) { return; } + List resources = new ArrayList<>(); BooleanPool pool = GenerateHashTreeUtil.isResourcePool(poolId); if (pool.isPool()) { resources = GenerateHashTreeUtil.setPoolResource(poolId); } + if (CollectionUtils.isEmpty(resources)) { client.delete(CONFIG + poolId); client.delete(EXEC_INDEX + poolId); return; } - Map configs = new HashMap<>(); - for (TestResource testResource : resources) { - String configuration = testResource.getConfiguration(); - if (StringUtils.isNotEmpty(configuration)) { - NodeDTO node = JSON.parseObject(configuration, NodeDTO.class); - String uri = String.format(BASE_URL + "/jmeter/api/start", node.getIp(), node.getPort()); - configs.put(uri, new ServerConfig(uri, 1, 1, node.getMaxConcurrency(), node.isEnable())); - } - } + Map configs = resources.stream() + .map(testResource -> { + String configuration = testResource.getConfiguration(); + if (StringUtils.isNotEmpty(configuration)) { + NodeDTO node = JSON.parseObject(configuration, NodeDTO.class); + String uri = String.format(BASE_URL + "/jmeter/api/start", node.getIp(), node.getPort()); + return new ServerConfig(uri, 1, 1, node.getMaxConcurrency(), node.isEnable()); + } + return null; + }) + .filter(Objects::nonNull) + .collect(Collectors.toMap(ServerConfig::getUrl, serverConfig -> serverConfig)); - if (client.opsForValue().get(CONFIG + poolId) == null) { + List existingConfigs = (List) client.opsForValue().get(CONFIG + poolId); + if (existingConfigs == null) { client.opsForValue().set(CONFIG + poolId, new ArrayList<>(configs.values())); } else { - // 合并相同节点信息,更改权重 - List serverConfigs = (List) client.opsForValue().get(CONFIG + poolId); - serverConfigs.forEach(item -> { - if (configs.containsKey(item.getUrl())) { - item.setCorePoolSize(configs.get(item.getUrl()).getCorePoolSize()); - item.setEnable(configs.get(item.getUrl()).isEnable()); - item.setWeight(configs.get(item.getUrl()).getWeight()); - } - }); - // 添加新增节点 - configs.forEach((k, v) -> { - if (!serverConfigs.contains(v)) { - serverConfigs.add(v); - } - }); - // 异常已经废弃的节点 - serverConfigs.removeIf(item -> !configs.containsKey(item.getUrl())); + Map existingConfigMap = existingConfigs.stream() + .collect(Collectors.toMap(ServerConfig::getUrl, serverConfig -> serverConfig)); - client.opsForValue().set(CONFIG + poolId, serverConfigs); + // 合并相同节点信息,更改权重 + existingConfigMap.forEach((url, existingConfig) -> { + if (configs.containsKey(url)) { + ServerConfig newConfig = configs.get(url); + existingConfig.setCorePoolSize(newConfig.getCorePoolSize()); + existingConfig.setEnable(newConfig.isEnable()); + existingConfig.setWeight(newConfig.getWeight()); + } + }); + + // 添加新增节点 + existingConfigs.addAll(configs.values().stream() + .filter(config -> !existingConfigMap.containsKey(config.getUrl())) + .toList()); + + // 移除废弃的节点 + existingConfigs.removeIf(config -> !configs.containsKey(config.getUrl())); + + client.opsForValue().set(CONFIG + poolId, existingConfigs); } + if (client.opsForValue().get(EXEC_INDEX + poolId) == null) { client.opsForValue().set(EXEC_INDEX + poolId, 1); } } - public static ServerConfig calculate(String poolId, RedisTemplate client) { + public static ServerConfig calculate(String poolId, RedisTemplate client) { if (client.opsForValue().get(EXEC_INDEX + poolId) == null) { client.opsForValue().set(EXEC_INDEX + poolId, 1); } - List serverList = new ArrayList<>(); - if (client.opsForValue().get(CONFIG + poolId) != null) { - serverList = (List) client.opsForValue().get(CONFIG + poolId); - } - // 最大权重 - int weightSum = serverList.stream().map(ServerConfig::getWeight).reduce((x, y) -> x += y).get(); - long execIndex = Long.parseLong(client.opsForValue().get(EXEC_INDEX + poolId).toString()); - // 选出当前有效权重最大的实例,将当前有效权重currentWeight减去所有实例的"权重和"(weightSum),且变量tmpSv指向此位置; - ServerConfig max = Collections.max(serverList, Comparator.comparingLong(ServerConfig::getCurrentWeight)); + List serverList = Optional.ofNullable((List) client.opsForValue().get(CONFIG + poolId)) + .orElse(new ArrayList<>()); + + // 最大权重 + int weightSum = serverList.stream() + .mapToInt(ServerConfig::getWeight) + .sum(); + + long execIndex = Long.parseLong(Objects.requireNonNull(client.opsForValue().get(EXEC_INDEX + poolId)).toString()); + + // 选出当前有效权重最大的实例 + ServerConfig max = serverList.stream() + .max(Comparator.comparingLong(ServerConfig::getCurrentWeight)) + .orElse(null); + // 选中的实例 ServerConfig tmpConfig = null; for (ServerConfig serverConfig : serverList) { - if (max.equals(serverConfig)) { + if (serverConfig.equals(max)) { serverConfig.setCurrentWeight(serverConfig.getCurrentWeight() - weightSum); if (tmpConfig == null || serverConfig.getCurrentWeight() > tmpConfig.getCurrentWeight()) { tmpConfig = serverConfig; } } - //将每个实例的当前有效权重currentWeight都加上配置权重weight; serverConfig.setCurrentWeight(serverConfig.getCurrentWeight() + serverConfig.getWeight()); } - // 选中前的当前权重 - LoggerUtil.info("第" + (execIndex) + "次选中前的当前权重:" + JSON.toJSONString(serverList)); + LoggerUtil.info(String.format("第%d次选中前的当前权重:%s", execIndex, JSON.toJSONString(serverList))); - if (client.opsForValue().get(CONFIG + poolId) != null) { - client.opsForValue().set(CONFIG + poolId, serverList); - } + client.opsForValue().set(CONFIG + poolId, serverList); return tmpConfig; } @@ -116,15 +128,13 @@ public class SmoothWeighted { if (pool.isPool()) { List resources = GenerateHashTreeUtil.setPoolResource(poolId); if (CollectionUtils.isNotEmpty(resources)) { - int index = (int) (Math.random() * resources.size()); + int index = new Random().nextInt(resources.size()); TestResource testResource = resources.get(index); NodeDTO node = JSON.parseObject(testResource.getConfiguration(), NodeDTO.class); - String nodeIp = node.getIp(); - Integer port = node.getPort(); - String uri = String.format(BASE_URL + "/jmeter/api/start", nodeIp, port); + String uri = String.format(BASE_URL + "/jmeter/api/start", node.getIp(), node.getPort()); return new ServerConfig(uri, 1, 1, node.getMaxConcurrency(), node.isEnable()); } } return null; } -} \ No newline at end of file +}