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);
+ }
+
}