From ff7dfdc1e4d0788e371588ba1d7fd665db0d5dc4 Mon Sep 17 00:00:00 2001 From: liuyunhu <3286117488@qq.com> Date: Wed, 17 Apr 2024 20:21:17 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=AC5=E6=AC=A1=E4=BC=98=E5=8C=96=20=20=20?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=B8=9A=E5=8A=A1=E5=88=86=E7=A6=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 30 ---- .../aliyun/service/AliYunEcsService.java | 10 +- src/main/java/com/lyh/job/Timer.java | 34 ++-- .../service/impl/LoadCenterServiceImpl.java | 165 +++++++++++++----- src/test/java/Test.java | 25 ++- 5 files changed, 164 insertions(+), 100 deletions(-) diff --git a/pom.xml b/pom.xml index bb961eb..7563a80 100644 --- a/pom.xml +++ b/pom.xml @@ -99,41 +99,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - com.aliyun darabonba-string 0.0.3 - - - - - diff --git a/src/main/java/com/lyh/common/aliyun/service/AliYunEcsService.java b/src/main/java/com/lyh/common/aliyun/service/AliYunEcsService.java index 8812f3d..eac94dc 100644 --- a/src/main/java/com/lyh/common/aliyun/service/AliYunEcsService.java +++ b/src/main/java/com/lyh/common/aliyun/service/AliYunEcsService.java @@ -6,11 +6,11 @@ import com.aliyun.ecs20140526.models.*; import com.aliyun.tea.TeaException; import com.aliyun.teautil.Common; import com.aliyun.teautil.models.RuntimeOptions; -import com.lyh.common.aliyun.model.InstanceSpecification; import com.lyh.common.aliyun.config.AliConfig; -import com.lyh.domain.InstancesInformation; +import com.lyh.common.aliyun.model.InstanceSpecification; import com.lyh.common.redis.service.RedisService; import com.lyh.common.utils.user.UserUtil; +import com.lyh.domain.InstancesInformation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -111,7 +111,7 @@ public class AliYunEcsService { DescribeInstancesResponse describeInstancesResp = DescribeInstances(client, aliConfig.getRegionId(), instanceIds, instanceName); instanceIds = ""; for (DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance instance : describeInstancesResp.body.instances.instance) { - instanceIds = "" + instance.instanceId + "," + instanceIds + ""; + instanceIds = instance.instanceId + "," + instanceIds; if (instance.deletionProtection) { ModifyInstanceAttribute(client, instance.instanceId); } @@ -276,7 +276,7 @@ public class AliYunEcsService { * @Description: 查询一台或多台实例的信息 多台实例用英文逗号拼接 * @Param: [instanceIds] i-uf6chlqotgoc9h173alu **/ - public List queryInstancesInformation(String instanceIds) throws Exception { + public List queryInstancesInformation(String instanceIds) { //初始化计数器 AtomicInteger count = new AtomicInteger(); @@ -364,4 +364,6 @@ public class AliYunEcsService { } return instances; } + + } diff --git a/src/main/java/com/lyh/job/Timer.java b/src/main/java/com/lyh/job/Timer.java index 81b39be..2e9ce6b 100644 --- a/src/main/java/com/lyh/job/Timer.java +++ b/src/main/java/com/lyh/job/Timer.java @@ -48,25 +48,29 @@ public class Timer { log.info(String.valueOf(response)); - JSONArray jsonArray = JSONArray.parseArray(response.body().string()); - JSONObject jsonObject = jsonArray.getJSONObject(0); - //获取mqttInfo对象的值 - JSONObject mqttInfo = jsonObject.getJSONObject("mqttInfo"); - //获取连接数 - int connectSize = mqttInfo.getIntValue("connectSize"); + JSONArray jsonArray = null; + if (null != response.body()) { + jsonArray = JSONArray.parseArray(response.body().string()); - log.info(ip + " 的fluxmq连接数为:" + connectSize); + JSONObject jsonObject = jsonArray.getJSONObject(0); + //获取mqttInfo对象的值 + JSONObject mqttInfo = jsonObject.getJSONObject("mqttInfo"); + //获取连接数 + int connectSize = mqttInfo.getIntValue("connectSize"); + + log.info(ip + " 的fluxmq连接数为:" + connectSize); - if (connectSize >= 80) { - //执行节点扩容 + if (connectSize >= 80) { + //执行节点扩容 - //返回实例的ID - String instanceId = aliYunEcsService.createAndRunInstance(); + //返回实例的ID + String instanceId = aliYunEcsService.createAndRunInstance(); - if (!instanceId.isEmpty()) { - log.info("扩容 成功!"); - log.info("扩容的节点ip为:" + instanceId); + if (!instanceId.isEmpty()) { + log.info("扩容 成功!"); + log.info("扩容的节点ip为:" + instanceId); + } } } @@ -76,4 +80,6 @@ public class Timer { } + + } diff --git a/src/main/java/com/lyh/service/impl/LoadCenterServiceImpl.java b/src/main/java/com/lyh/service/impl/LoadCenterServiceImpl.java index 2ed1262..c9aa193 100644 --- a/src/main/java/com/lyh/service/impl/LoadCenterServiceImpl.java +++ b/src/main/java/com/lyh/service/impl/LoadCenterServiceImpl.java @@ -3,17 +3,18 @@ package com.lyh.service.impl; import com.alibaba.fastjson2.JSON; import com.aliyun.ecs20140526.models.DescribeInstancesResponseBody; import com.lyh.common.aliyun.service.AliYunEcsService; +import com.lyh.common.redis.service.RedisService; +import com.lyh.common.utils.mqtt.MqttUtil; +import com.lyh.common.utils.user.UserUtil; import com.lyh.domain.IpAndLoadCount; import com.lyh.domain.IpAndWeight; import com.lyh.domain.resp.Result; -import com.lyh.common.redis.service.RedisService; -import com.lyh.common.utils.user.UserUtil; -import com.lyh.common.utils.mqtt.MqttUtil; import com.lyh.service.LoadCenterService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; @@ -45,75 +46,150 @@ public class LoadCenterServiceImpl implements LoadCenterService { @Override public Result getAssignedServer() { - //存IP的List - ArrayList ipList = new ArrayList<>(); - //获取上海区的实例ID列表 - try { + //刷新一下 实例公网IP列 缓存 + this.getEcsIPList(); - List idList = aliYunEcsService.getIDList(); - idList.forEach(id -> { - //调用方法,获取对应ID实例的IP - try { - List result = aliYunEcsService.queryInstancesInformation(id); - - //获取集合第一个的属性 - DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance response = result.get(0); - - //获取添加的实例的公网ip - String instanceIp = UserUtil.removeBrackets(response.getPublicIpAddress().getIpAddress().toString()); - ipList.add(instanceIp); - - } catch (Exception e) { - log.error(e.getMessage()); - } - }); - } catch (Exception e) { - log.error(e.getMessage()); + //从缓存中获取实例公网IP列表 + if (redis.getCacheList("实例IP列表:").isEmpty()) { + throw new RuntimeException("实例IP列表为空!"); } - log.info(JSON.toJSONString(ipList)); + //将结果转成JSON串 + String string = JSON.toJSONString(redis.getCacheList("实例IP列表:")); + //再转成String泛型 的 List + List ecsIPList = JSON.parseArray(string, String.class); + + + //通过IP列表 获取各个IP对应的负载量 + List ipAndLoadCounts = this.getIpAndLoadCounts(ecsIPList); + + //通过IP和对应的负载量,计算出IP对应的权重 + List ipAndWeights = this.getIpAndWeights(ipAndLoadCounts); + + //通过IP和权重,计算负载节点的IP列表 + List loadNodeList = this.getLoadNodeListByIpAndWeights(ipAndWeights); + + + //获取缓存里最后一个IP进行返回 + //最后一个IP进行返回 + String result = loadNodeList.get(loadNodeList.size() - 1); + + return Result.success(result); + } + + + /* + * @Author: LiuYunHu + * @Date: 2024/4/17 17:14 + * @Description: 获取所有实例公网的IP列表 + * @Param: [] + * @Return: List + **/ + @PostConstruct + public void getEcsIPList() { + //存IP的List + ArrayList ecsIPList = new ArrayList<>(); + + try { + //获取上海区的实例ID列表 + List ecsIDList = aliYunEcsService.getIDList(); + + //将ID进行拼接,用逗号分隔 + String ids = ""; + for (String id : ecsIDList) { + ids += id + ","; + } + ids = ids.substring(0, ids.length() - 1); + + List response = aliYunEcsService.queryInstancesInformation(ids); + + response.forEach(item -> { + //获取添加的实例的公网ip + String ip = UserUtil.removeBrackets(item.getPublicIpAddress().getIpAddress().toString()); + ecsIPList.add(ip); + }); + + } catch (Exception e) { + log.error("获取实例ID列表失败:{}", e.getMessage()); + throw new RuntimeException(e); + } //将IP列表存入redis - redis.deleteObject("服务器列表:"); - redis.setCacheList("服务器列表:", ipList); + redis.deleteObject("实例IP列表:"); + redis.setCacheList("实例IP列表:", ecsIPList); + log.info("实例公网IP列表:{}", ecsIPList); + } + + + /* + * @Author: LiuYunHu + * @Date: 2024/4/17 19:41 + * @Description: 通过IP获取各个IP的负载量 + * @Param: ecsIPList + * @Return: List + **/ + public List getIpAndLoadCounts(List ecsIPList) { //存各个 服务器的负载量 ArrayList ipAndLoadCounts = new ArrayList<>(); - - ipList.forEach(ip -> { - - //拿到IP后,获取各个IP的负载量 + //拿到IP后,获取各个IP的负载量 + ecsIPList.forEach(ip -> { int fetchLoad = mqttUtil.getFetchLoad(ip); ipAndLoadCounts.add(new IpAndLoadCount(ip, fetchLoad)); }); + log.info("各个IP的负载量:{}", ipAndLoadCounts); + return ipAndLoadCounts; + } + + + /* + * @Author: LiuYunHu + * @Date: 2024/4/17 19:49 + * @Description: 通过IP和对应的负载量,计算出IP对应的权重 + * @Param: ipAndLoadCountList + * @Return: List + **/ + public List getIpAndWeights(List ipAndLoadCounts) { //求出空负载的总量 int emptyLoadCount = 0; for (IpAndLoadCount ipAndLoadCount : ipAndLoadCounts) { - - //假设使用2/8原则 + //假设使用2/8原则 一个节点最多能有100个连接 emptyLoadCount += (80 - ipAndLoadCount.getLoadCount()); } - //存储IP和对应的权重 ArrayList ipAndWeights = new ArrayList<>(); for (IpAndLoadCount ipAndLoadCount : ipAndLoadCounts) { - IpAndWeight ipAndWeight = new IpAndWeight(ipAndLoadCount.getIp(), (80 - ipAndLoadCount.getLoadCount()) * 100 / emptyLoadCount); + IpAndWeight ipAndWeight = new IpAndWeight( + ipAndLoadCount.getIp(), + (80 - ipAndLoadCount.getLoadCount()) * 100 / emptyLoadCount + ); ipAndWeights.add(ipAndWeight); } - log.info(JSON.toJSONString(ipAndWeights));//[IpAndWeight(nodeIp=47.102.158.233, weight=55), IpAndWeight(nodeIp=47.102.123.209, weight=44)] + log.info("实例IP和对应的权重:{}", ipAndWeights);//[IpAndWeight(nodeIp=47.102.158.233, weight=55), IpAndWeight(nodeIp=47.102.123.209, weight=44)] + return ipAndWeights; + } - //*******************************************以下为改老师的代码 + /* + * @Author: LiuYunHu + * @Date: 2024/4/17 20:02 + * @Description: 通过IP和权重,计算负载节点的IP列表 TODO + * @Param: [] + * @Return: + **/ + public List getLoadNodeListByIpAndWeights(List ipAndWeights) { ArrayList loadNodeList = new ArrayList<>(); - int sum = ipAndWeights.stream().mapToInt(IpAndWeight::getWeight).sum(); + int sum = ipAndWeights.stream() + .mapToInt(IpAndWeight::getWeight) + .sum(); if (sum < 100) { List list = ipAndWeights.stream().sorted(((o1, o2) -> o2.getWeight() - o1.getWeight())).toList(); @@ -147,14 +223,9 @@ public class LoadCenterServiceImpl implements LoadCenterService { redis.deleteObject("work:node:gateway"); redis.setCacheList("work:node:gateway", loadNodeList); - - //获取缓存里最后一个IP进行返回 - //最后一个IP进行返回 - String result = loadNodeList.get(loadNodeList.size() - 1); - - return Result.success(result); + log.info("负载节点的IP列表:{}", loadNodeList); + return loadNodeList; } - } diff --git a/src/test/java/Test.java b/src/test/java/Test.java index 866e265..0baa530 100644 --- a/src/test/java/Test.java +++ b/src/test/java/Test.java @@ -1,7 +1,6 @@ import com.aliyun.ecs20140526.models.DescribeInstancesResponseBody; import com.lyh.LoadCenterApplication; import com.lyh.common.aliyun.service.AliYunEcsService; -import com.lyh.common.redis.service.RedisService; import com.lyh.common.utils.user.UserUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -20,8 +19,6 @@ import java.util.List; @SpringBootTest(classes = LoadCenterApplication.class) @Slf4j public class Test { - @Autowired - private RedisService redisService; @Autowired private AliYunEcsService aliYunEcsService; @@ -75,7 +72,7 @@ public class Test { **/ @org.junit.jupiter.api.Test public void releaseInstances() throws Exception { - aliYunEcsService.releaseInstances("i-uf6if4mw6iu6rjffrs2c,i-uf6a4lwh3qdqwa5t5237"); + aliYunEcsService.releaseInstances("i-uf624nmh7j2nzlzxnd1u"); } /* @@ -90,8 +87,26 @@ public class Test { String instanceId = aliYunEcsService.createAndRunInstance(); System.out.println(instanceId); - } + @org.junit.jupiter.api.Test + public void aaaaaa() { + //获取上海区的实例ID列表 + List ecsIDList = null; + try { + ecsIDList = aliYunEcsService.getIDList(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + //将ID进行拼接,用逗号分隔 + String ids = ""; + for (String id : ecsIDList) { + ids += id + ","; + } + ids = ids.substring(0, ids.length() - 1); + log.info(ids); + } + }