master
parent
458b6747dd
commit
d7c5b3a4d4
10
pom.xml
10
pom.xml
|
@ -8,9 +8,9 @@
|
|||
<artifactId>vehicle</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<properties>
|
||||
<maven.compiler.source>20</maven.compiler.source>
|
||||
<maven.compiler.target>20</maven.compiler.target>
|
||||
<spring-boot.version>2.7.18</spring-boot.version>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<spring-boot.version>2.7.13</spring-boot.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
|
@ -218,8 +218,4 @@
|
|||
|
||||
</build>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</project>
|
||||
|
|
|
@ -17,18 +17,16 @@ import org.springframework.context.annotation.Configuration;
|
|||
* @Author ZeJinG.Su
|
||||
*/
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "config.aliyun")
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
@SuperBuilder
|
||||
@ConfigurationProperties(prefix = "config.ali")
|
||||
public class AliConfig {
|
||||
|
||||
/**
|
||||
* 阿里云access-key-id
|
||||
*/
|
||||
private String accessKetId;
|
||||
private String accessKeyId;
|
||||
/**
|
||||
* 阿里云access-key-secret
|
||||
*/
|
||||
|
@ -42,7 +40,7 @@ public class AliConfig {
|
|||
@Bean
|
||||
public Client createEcsClient(AliConfig aliConfig) throws Exception {
|
||||
Config config = new Config()
|
||||
.setAccessKeyId(aliConfig.getAccessKetId())
|
||||
.setAccessKeyId(aliConfig.getAccessKeyId())
|
||||
.setAccessKeySecret(aliConfig.getAccessKeySecret())
|
||||
.setRegionId(aliConfig.getRegionId());
|
||||
return new Client(config);
|
||||
|
|
|
@ -5,7 +5,10 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
*创建实例的参数映射yml
|
||||
* @ClassName InstanceConfig
|
||||
* @Description 创建实例的参数映射yml
|
||||
* @Author ZeJinG.Su
|
||||
* @Date 10:39 2024/4/20
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
|
|
|
@ -40,7 +40,11 @@ public class AliYunEcsService {
|
|||
}
|
||||
|
||||
|
||||
//区域实例集合
|
||||
/**
|
||||
* 区域实例集合
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public List<String> getIDList() throws Exception {
|
||||
|
||||
List<String> regionIds = com.aliyun.darabonbastring.Client.split(aliConfig.getRegionId(), ",", 50);
|
||||
|
@ -63,7 +67,11 @@ public class AliYunEcsService {
|
|||
return result;
|
||||
}
|
||||
|
||||
//释放实例
|
||||
/**
|
||||
* 释放实例
|
||||
* @param instanceIds
|
||||
* @throws Exception
|
||||
*/
|
||||
public void releaseInstances(String instanceIds) throws Exception {
|
||||
|
||||
// 实例名称,支持使用通配符*进行模糊搜索
|
||||
|
@ -96,7 +104,15 @@ public class AliYunEcsService {
|
|||
DeleteInstances(client, aliConfig.getRegionId(), instanceIds, force);
|
||||
}
|
||||
|
||||
//查询需要删除实例
|
||||
/**
|
||||
* 查询需要删除实例
|
||||
* @param client
|
||||
* @param regionId
|
||||
* @param instanceIds
|
||||
* @param instanceName
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static DescribeInstancesResponse DescribeInstances(Client client, String regionId, String instanceIds, String instanceName) throws Exception {
|
||||
DescribeInstancesRequest req = new DescribeInstancesRequest()
|
||||
.setRegionId(regionId)
|
||||
|
@ -110,7 +126,12 @@ public class AliYunEcsService {
|
|||
return resp;
|
||||
}
|
||||
|
||||
//修改实例删除保护
|
||||
/**
|
||||
* 修改实例删除保护
|
||||
* @param client
|
||||
* @param instatnceId
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void ModifyInstanceAttribute(Client client, String instatnceId) throws Exception {
|
||||
ModifyInstanceAttributeRequest req = new ModifyInstanceAttributeRequest()
|
||||
.setInstanceId(instatnceId)
|
||||
|
@ -119,7 +140,14 @@ public class AliYunEcsService {
|
|||
com.aliyun.teaconsole.Client.log("--------------------" + instatnceId + "释放保护取消成功--------------------");
|
||||
}
|
||||
|
||||
//执行释放实例
|
||||
/**
|
||||
* 执行释放实例
|
||||
* @param client
|
||||
* @param regionId
|
||||
* @param instanceIds
|
||||
* @param force
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void DeleteInstances(Client client, String regionId, String instanceIds, String force) throws Exception {
|
||||
DeleteInstancesRequest req = new DeleteInstancesRequest()
|
||||
.setRegionId(regionId)
|
||||
|
@ -131,34 +159,22 @@ public class AliYunEcsService {
|
|||
}
|
||||
|
||||
|
||||
//创建实例(创建成功后自启动)
|
||||
/**
|
||||
* 创建实例(创建成功后自启动)
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public String createAndRunInstance() throws Exception {
|
||||
|
||||
//获取实例规格
|
||||
// 地域Id
|
||||
String regionId = aliConfig.getRegionId();
|
||||
// 镜像 ID,启动实例时选择的镜像资源。
|
||||
String imageId = instanceConfig.getImageId();
|
||||
// 实例规格
|
||||
String instanceType = instanceConfig.getInstanceType();
|
||||
// 新创建实例所属于的安全组 ID。
|
||||
String securityGroupId = instanceConfig.getSecurityGroupId();
|
||||
// 虚拟交换机 ID。
|
||||
String vSwitchId = instanceConfig.getVSwitchId();
|
||||
// 公网出带宽最大值,单位为 Mbit/s。取值范围:0~100。 默认值:0。
|
||||
Integer internetMaxBandwidthOut = com.aliyun.darabonbanumber.Client.parseInt(instanceConfig.getInternetMaxBandwidthOut());
|
||||
// 网络计费类型。取值范围:
|
||||
// PayByBandwidth: 按固定带宽计费。
|
||||
// PayByTraffic: 按使用流量计费。
|
||||
// 默认值:PayByTraffic。
|
||||
String internetChargeType = instanceConfig.getInternetChargeType();
|
||||
// 系统盘大小
|
||||
String size = instanceConfig.getSize();
|
||||
// 系统盘的云盘种类
|
||||
String category = instanceConfig.getCategory();
|
||||
// ECS实例的计费方式
|
||||
// PrePaid:包年包月
|
||||
// PostPaid:按量付费
|
||||
String instanceChargeType = instanceConfig.getInstanceChargeType();
|
||||
|
||||
|
||||
|
@ -213,7 +229,11 @@ public class AliYunEcsService {
|
|||
}
|
||||
|
||||
|
||||
//查询实例信息
|
||||
/**
|
||||
* 查询实例信息
|
||||
* @param instanceIds
|
||||
* @return
|
||||
*/
|
||||
public List<DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance> queryInstancesInformation(String instanceIds) {
|
||||
|
||||
DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest()
|
||||
|
|
|
@ -16,18 +16,42 @@ import lombok.NoArgsConstructor;
|
|||
@AllArgsConstructor
|
||||
public class GatewayNodeInfo {
|
||||
/**
|
||||
* 节点ID
|
||||
* 实例ID
|
||||
*/
|
||||
private String nodeId;
|
||||
private String instanceId;
|
||||
|
||||
/**
|
||||
* 公网IP地址
|
||||
* 名称
|
||||
*/
|
||||
private String publicIdAddress;
|
||||
private String instanceName;
|
||||
|
||||
/**
|
||||
* 内网IP地址
|
||||
* 状态
|
||||
*/
|
||||
private String privateIdAddress;
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 公网IP
|
||||
*/
|
||||
private String publicIpAddress;
|
||||
|
||||
/**
|
||||
* 私网IP
|
||||
*/
|
||||
private String privateIpAddress;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private String creationTime;
|
||||
|
||||
/**
|
||||
* 到期时间
|
||||
*/
|
||||
private String expiredTime;
|
||||
|
||||
/**
|
||||
* 是否可回收
|
||||
*/
|
||||
private Boolean recyclable;
|
||||
}
|
||||
|
|
|
@ -10,13 +10,14 @@ import com.loadCenter.aliyun.gateway.model.NodeLoadNum;
|
|||
import com.loadCenter.aliyun.gateway.model.NodeLoadWeight;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @ClassName HandleCache
|
||||
|
@ -29,60 +30,313 @@ import java.util.List;
|
|||
@Component
|
||||
@AllArgsConstructor
|
||||
public class HandleCache {
|
||||
@Autowired
|
||||
private MqttUtil mqttUtil;
|
||||
|
||||
@Autowired
|
||||
private AliYunEcsService aliYunEcsService;
|
||||
private final MqttUtil mqttUtil;
|
||||
|
||||
/*
|
||||
* 操作网关节点缓存
|
||||
* */
|
||||
@Autowired
|
||||
private GatewayNodeInfoCache gatewayNodeInfoCache;
|
||||
|
||||
/*
|
||||
private final AliYunEcsService aliYunEcsService;
|
||||
|
||||
/**
|
||||
* 网关节点缓存操作
|
||||
*/
|
||||
private final GatewayNodeInfoCache gatewayNodeInfoCache;
|
||||
|
||||
/**
|
||||
* 操作负载节点IP缓存
|
||||
* */
|
||||
@Autowired
|
||||
private GatewayNodeIPCache gatewayNodeIpCache;
|
||||
*/
|
||||
private final GatewayNodeIPCache gatewayNodeIPCache;
|
||||
|
||||
/*
|
||||
* 操作负载节点ID缓存
|
||||
* */
|
||||
@Autowired
|
||||
private GatewayNodeIDCache gatewayNodeIdCache;
|
||||
/**
|
||||
* 操作节点ID缓存
|
||||
*/
|
||||
private final GatewayNodeIDCache gatewayNodeIDCache;
|
||||
|
||||
/*
|
||||
* 操作实例IP和负载量缓存
|
||||
* */
|
||||
@Autowired
|
||||
private GatewayIpLoadCountKey gatewayIpLoadCountKey;
|
||||
/**
|
||||
* 操作节点权重缓存
|
||||
*/
|
||||
private final GatewayWeightCache gatewayWeightCache;
|
||||
|
||||
/*
|
||||
* 操作实例IP和权重缓存
|
||||
* */
|
||||
@Autowired
|
||||
private GatewayWeightCache gatewayWeightCache;
|
||||
/**
|
||||
* 操作节点IP负载计数缓存
|
||||
*/
|
||||
private final GatewayIpLoadCountKey gatewayIpLoadCountKey;
|
||||
|
||||
/*
|
||||
* 操作实例IP序列缓存
|
||||
* */
|
||||
@Autowired
|
||||
private GatewayOrderCache gatewayOrderCache;
|
||||
/**
|
||||
* 操作节点ID排序缓存
|
||||
*/
|
||||
private final GatewayOrderCache gatewayOrderCache;
|
||||
|
||||
// //刷新所有的缓存
|
||||
// @Scheduled(cron = "0/2 * * * * ?")
|
||||
// public void refreshAllCache() {
|
||||
// this.getNodeIDList();
|
||||
// this.getNodeInfos();
|
||||
// this.getNodeIPList();
|
||||
// this.getIpAndLoadCounts();
|
||||
// this.getIpAndWeights();
|
||||
// this.getLoadNodeOrderListByIpAndWeights();
|
||||
// }
|
||||
/**
|
||||
* 定时任务,每隔5秒执行一次
|
||||
*/
|
||||
@Scheduled(fixedRate = 5000)
|
||||
public void handleCache() {
|
||||
//节点列表缓存刷新
|
||||
this.getNodeIDList();
|
||||
//实例信息缓存刷新
|
||||
this.getNodeInfo();
|
||||
//节点公网IP列表缓存刷新
|
||||
this.getNodeIPList();
|
||||
//各个IP的负载量缓存刷新
|
||||
this.getIpAndLoadCounts();
|
||||
//各个IP的权重缓存刷新
|
||||
this.getIpAndWeights();
|
||||
//负载节点IP序列缓存刷新
|
||||
this.getLoadNodeOrderListByIpAndWeights();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取节点ID列表
|
||||
*/
|
||||
@PostConstruct
|
||||
public void getNodeIDList(){
|
||||
try {
|
||||
//获取实例列表
|
||||
List<String> idList = aliYunEcsService.getIDList();
|
||||
//为空则创建新节点
|
||||
if(idList == null || idList.isEmpty()){
|
||||
aliYunEcsService.createAndRunInstance();
|
||||
}
|
||||
log.info("实例ID列表:{}", idList);
|
||||
gatewayNodeIDCache.put(idList);
|
||||
} catch (Exception e) {
|
||||
log.error("获取实例ID列表失败:" + e.getMessage());
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实例信息
|
||||
*/
|
||||
public void getNodeInfo() {
|
||||
Long count = 0L;
|
||||
|
||||
ArrayList<GatewayNodeInfo> gatewayNodeInfos = new ArrayList<>();
|
||||
|
||||
try {
|
||||
|
||||
//获取ID集合
|
||||
List<String> ecsIDList = gatewayNodeIDCache.get();
|
||||
if (ecsIDList == null || ecsIDList.isEmpty()) {
|
||||
log.error("实例ID为空");
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder ids = new StringBuilder();
|
||||
for (String id : ecsIDList) {
|
||||
ids.append(id).append(",");
|
||||
}
|
||||
ids = new StringBuilder(ids.substring(0, ids.length() - 1));
|
||||
|
||||
//查询所有ID实例的详细信息
|
||||
List<DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance> response = aliYunEcsService.queryInstancesInformation(ids.toString());
|
||||
|
||||
|
||||
for (DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance item : response) {
|
||||
|
||||
log.info("查询第{}个实例的ID:{}" ,count+1, item.getInstanceId());
|
||||
|
||||
log.info("地域ID:{}",item.getRegionId());
|
||||
|
||||
log.info("CPU核心数:{}", item.getCpu());
|
||||
|
||||
log.info("内存大小:{}MB", item.getMemory());
|
||||
|
||||
log.info("公网出带宽值:{}Mbit/s",item.getInternetMaxBandwidthOut() + "");
|
||||
|
||||
log.info("公网IP:{}", UserUtil.removeBrackets(item.getPublicIpAddress().getIpAddress().toString()));
|
||||
|
||||
log.info("私网IP:{}", UserUtil.removeBrackets(item.getVpcAttributes().getPrivateIpAddress().ipAddress.toString()));
|
||||
|
||||
log.info("创建时间:{}",item.getCreationTime());
|
||||
|
||||
log.info("过期时间:{}",item.getExpiredTime());
|
||||
|
||||
log.info("是否可回收:{}",item.getRecyclable());
|
||||
|
||||
log.info("实例名称:{}",item.getInstanceName());
|
||||
|
||||
log.info("实例状态:{}",item.getStatus());
|
||||
|
||||
log.info("-----------------------------分割线-----------------------------------"+"/n/n/n");
|
||||
|
||||
|
||||
//实例状态为运行中才加入列表
|
||||
//停止的实例不加入列表
|
||||
if(item.getStatus().equals("Stopped")){
|
||||
//停止的实例不加入列表
|
||||
log.info("实例状态为停止,不加入列表");
|
||||
continue;
|
||||
}
|
||||
//运行中
|
||||
if (item.getStatus().equals("Running")) {
|
||||
//存入集合
|
||||
gatewayNodeInfos.add(
|
||||
new GatewayNodeInfo(
|
||||
item.getInstanceId(),
|
||||
item.getInstanceName(),
|
||||
item.getStatus(),
|
||||
UserUtil.removeBrackets(item.getPublicIpAddress().getIpAddress().toString()),
|
||||
UserUtil.removeBrackets(item.getVpcAttributes().getPrivateIpAddress().ipAddress.toString()),
|
||||
item.getCreationTime(),
|
||||
item.getExpiredTime(),
|
||||
item.getRecyclable()
|
||||
)
|
||||
);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("获取实例列表失败:" + e.getMessage());
|
||||
}
|
||||
log.info("实例信息列表:{}", gatewayNodeInfos);
|
||||
|
||||
//存入缓存
|
||||
gatewayNodeInfoCache.put(gatewayNodeInfos);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取节点公网IP列表
|
||||
*/
|
||||
public void getNodeIPList() {
|
||||
//存IP的List
|
||||
ArrayList<String> nodeIPList = new ArrayList<>();
|
||||
|
||||
//从缓存中拿到实例信息列表
|
||||
List<GatewayNodeInfo> gatewayNodeInfoList = gatewayNodeInfoCache.get();
|
||||
|
||||
if (gatewayNodeInfoList.isEmpty()) {
|
||||
log.error("实例信息列表为空!");
|
||||
return;
|
||||
}
|
||||
|
||||
gatewayNodeInfoList.forEach(item -> {
|
||||
//获取IP
|
||||
String ip = item.getPublicIpAddress();
|
||||
//存入集合
|
||||
nodeIPList.add(ip);
|
||||
});
|
||||
|
||||
|
||||
log.info("实例公网IP列表:{}", nodeIPList);
|
||||
|
||||
//将IP列表存入redis
|
||||
gatewayNodeIPCache.put(nodeIPList);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取各个IP的负载量
|
||||
*/
|
||||
public void getIpAndLoadCounts() {
|
||||
//从缓存中获取实例公网IP列表
|
||||
List<String> nodeIPList = gatewayNodeIPCache.get();
|
||||
if (nodeIPList.isEmpty()) {
|
||||
log.error("实例公网IP列表为空!");
|
||||
return;
|
||||
}
|
||||
|
||||
//存各个 服务器的负载量
|
||||
ArrayList<NodeLoadNum> ipAndLoadCounts = new ArrayList<>();
|
||||
|
||||
//拿到IP后,获取各个IP的负载量
|
||||
nodeIPList.forEach(ip -> {
|
||||
ipAndLoadCounts.add(mqttUtil.getFetchLoad(ip));
|
||||
});
|
||||
|
||||
log.info("各个IP的负载量:{}", ipAndLoadCounts);
|
||||
|
||||
gatewayIpLoadCountKey.put(ipAndLoadCounts);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算各个IP的权重
|
||||
*/
|
||||
public void getIpAndWeights() {
|
||||
//从缓存中获取公网IP和负载量列表
|
||||
List<NodeLoadNum> ipAndLoadCounts = gatewayIpLoadCountKey.get();
|
||||
if (ipAndLoadCounts.isEmpty()) {
|
||||
log.error("负载量列表为空!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//求出空负载的总量
|
||||
int emptyLoadCount = 0;
|
||||
for (NodeLoadNum ipAndLoadCount : ipAndLoadCounts) {
|
||||
//假设使用2/8原则 一个节点最多能有100个连接
|
||||
emptyLoadCount += (80 - ipAndLoadCount.getLoadNum());
|
||||
}
|
||||
|
||||
//存储IP和对应的权重
|
||||
ArrayList<NodeLoadWeight> ipAndWeights = new ArrayList<>();
|
||||
for (NodeLoadNum ipAndLoadCount : ipAndLoadCounts) {
|
||||
|
||||
NodeLoadWeight ipAndWeight = new NodeLoadWeight(
|
||||
ipAndLoadCount.getIpName(),
|
||||
(80 - ipAndLoadCount.getLoadNum()) * 100 / emptyLoadCount
|
||||
);
|
||||
ipAndWeights.add(ipAndWeight);
|
||||
}
|
||||
|
||||
log.info("实例IP和对应的权重:{}", ipAndWeights);//[IpAndWeight(nodeIp=47.102.158.233, weight=55), IpAndWeight(nodeIp=47.102.123.209, weight=44)]
|
||||
|
||||
gatewayWeightCache.put(ipAndWeights);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取负载节点IP序列
|
||||
*/
|
||||
public void getLoadNodeOrderListByIpAndWeights() {
|
||||
//从缓存中获取公网IP和权重列表
|
||||
List<NodeLoadWeight> ipAndWeights = gatewayWeightCache.get();
|
||||
if (ipAndWeights.isEmpty()) {
|
||||
log.error("负载节点IP和权重列表为空!");
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList<String> loadNodeList = new ArrayList<>();
|
||||
|
||||
Long sum = ipAndWeights.stream()
|
||||
.mapToLong(NodeLoadWeight::getWeight)
|
||||
.sum();
|
||||
if (sum < 100) {
|
||||
List<NodeLoadWeight> list = ipAndWeights.stream()
|
||||
.sorted(Comparator.comparingLong(NodeLoadWeight::getWeight).reversed())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
//给权重高的节点 权重再加一个
|
||||
int countWeight = 0;
|
||||
for (Long i = sum; i < 100; i++) {
|
||||
NodeLoadWeight ipAndWeight = list.get(countWeight++ % list.size());
|
||||
ipAndWeight.setWeight(ipAndWeight.getWeight() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
whFor:
|
||||
while (true) {
|
||||
for (NodeLoadWeight ipAndWeight : ipAndWeights) {
|
||||
Long weight = ipAndWeight.getWeight();
|
||||
if (weight > 0) {
|
||||
loadNodeList.add(ipAndWeight.getIpName());
|
||||
}
|
||||
ipAndWeight.setWeight(weight - 1);
|
||||
}
|
||||
|
||||
Long sum1 = ipAndWeights.stream()
|
||||
.mapToLong(NodeLoadWeight::getWeight)
|
||||
.sum();
|
||||
if (sum1 <= 0) {
|
||||
break whFor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//IP序列存入缓存
|
||||
gatewayOrderCache.put(loadNodeList);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,103 +0,0 @@
|
|||
package com.loadCenter.aliyun.job;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.loadCenter.aliyun.common.aliyun.service.AliYunEcsService;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.loadCenter.aliyun.common.redis.service.RedisService;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* @ClassName LoadCenterController
|
||||
* @Author ZeJinG.Su
|
||||
*/
|
||||
@Component
|
||||
@Log4j2
|
||||
public class LoadCenterController {
|
||||
int aa=0;
|
||||
int bb=0;
|
||||
@Autowired
|
||||
StringRedisTemplate redisTemplate;
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
@Autowired
|
||||
private AliYunEcsService aliYunEcsService;
|
||||
|
||||
/*
|
||||
* 30秒扫描一次服务器,负载情况
|
||||
*/
|
||||
@Scheduled(cron = "0/5 * * * * ?")
|
||||
public void scheduleECS() throws Exception {
|
||||
//假设这里出现了超出预设连接数大于80%,则进行扩容
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
Set<String> ipCacheSet = redisService.getCacheZSet("ECS");
|
||||
log.info("共有个"+ipCacheSet.size()+"服务器");
|
||||
|
||||
for (String ip : ipCacheSet) {
|
||||
|
||||
String URL = "http://"+ip+":8080/public/cluster";
|
||||
Request request = new Request.Builder()
|
||||
.url(URL)
|
||||
.get()
|
||||
.addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
|
||||
.addHeader("Accesstoken", "")
|
||||
.build();
|
||||
|
||||
try {
|
||||
Response response = client.newCall(request).execute();
|
||||
|
||||
JSONArray jsonArray = JSONArray.parseArray(response.body().string());
|
||||
JSONObject jsonObject = jsonArray.getJSONObject(0);
|
||||
JSONObject mqttInfo = jsonObject.getJSONObject("mqttInfo");
|
||||
int connectSize = mqttInfo.getIntValue("connectSize");
|
||||
|
||||
log.info("服务器:"+ip+"-车辆连接数:"+connectSize);
|
||||
|
||||
redisService.setCacheZSet("ECS", ip,connectSize);
|
||||
|
||||
if (connectSize>=5){
|
||||
aa++;
|
||||
log.info("服务器:"+ip+"-----"+aa+"=="+ipCacheSet.size()+"就可以扩容");
|
||||
|
||||
if (aa==ipCacheSet.size()){
|
||||
|
||||
log.info("服务器个数:"+ipCacheSet.size()+",-----循环第"+aa+"次,相等了,需要扩容");
|
||||
log.info("执行扩容机制");
|
||||
|
||||
log.info("扩容中休眠5秒,再返回,确保先创建,确保查询得到结果-------");
|
||||
Thread.sleep(5000);
|
||||
|
||||
|
||||
log.info("实例id和公网ip存入redis");
|
||||
aa=0;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
aa=0;
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
package com.loadCenter.aliyun.job;
|
||||
|
||||
import com.loadCenter.aliyun.common.aliyun.service.AliYunEcsService;
|
||||
import com.loadCenter.aliyun.gateway.cache.GatewayIpLoadCountKey;
|
||||
import com.loadCenter.aliyun.gateway.cache.GatewayNodeIDCache;
|
||||
import com.loadCenter.aliyun.gateway.cache.GatewayNodeInfoCache;
|
||||
import com.loadCenter.aliyun.gateway.model.GatewayNodeInfo;
|
||||
import com.loadCenter.aliyun.gateway.model.NodeLoadNum;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @ClassName ScheduledTask
|
||||
* @Author ZeJinG.Su
|
||||
*/
|
||||
@Component
|
||||
@Log4j2
|
||||
public class ScheduledTask {
|
||||
|
||||
/*
|
||||
* 阿里云api接口类
|
||||
* */
|
||||
private final AliYunEcsService aliYunEcsService;
|
||||
|
||||
/*
|
||||
* 操作缓存
|
||||
* */
|
||||
private final GatewayIpLoadCountKey gatewayIpLoadCountKey;
|
||||
|
||||
private final GatewayNodeIDCache gatewayNodeIdCache;
|
||||
|
||||
private final GatewayNodeInfoCache gatewayNodeInfoCache;
|
||||
|
||||
public ScheduledTask(AliYunEcsService aliYunEcsService, GatewayIpLoadCountKey gatewayIpLoadCountKey, GatewayNodeIDCache gatewayNodeIdCache, GatewayNodeInfoCache gatewayNodeInfoCache) {
|
||||
this.aliYunEcsService = aliYunEcsService;
|
||||
this.gatewayIpLoadCountKey = gatewayIpLoadCountKey;
|
||||
this.gatewayNodeIdCache = gatewayNodeIdCache;
|
||||
this.gatewayNodeInfoCache = gatewayNodeInfoCache;
|
||||
}
|
||||
|
||||
|
||||
@Scheduled(cron = "0/10 * * * * ?")
|
||||
/**
|
||||
* 动态扩容
|
||||
*/
|
||||
public void dynamicExpansion() {
|
||||
//先获取所有的负载列表
|
||||
List<NodeLoadNum> ipAndLoadCounts = gatewayIpLoadCountKey.get();
|
||||
if (ipAndLoadCounts.isEmpty()) {
|
||||
log.error("负载量列表为空!");
|
||||
return;
|
||||
}
|
||||
|
||||
//计算所有节点的负载
|
||||
Long connectSize = ipAndLoadCounts.stream().mapToLong(NodeLoadNum::getLoadNum).sum();
|
||||
|
||||
//求出平均值
|
||||
Long avg = connectSize / ipAndLoadCounts.size();
|
||||
|
||||
if (avg >= 80) {
|
||||
//执行节点扩容
|
||||
|
||||
//返回实例的ID
|
||||
String instanceId;
|
||||
try {
|
||||
instanceId = aliYunEcsService.createAndRunInstance();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("节点扩容失败!" + e.getMessage());
|
||||
}
|
||||
|
||||
if (!instanceId.isEmpty()) {
|
||||
log.info("扩容 成功!扩容的节点ip为:" + instanceId);
|
||||
}
|
||||
} else {
|
||||
log.info("暂时不需要扩容");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Scheduled(cron = "0/10 * * * * ?")
|
||||
/**
|
||||
* 动态缩容
|
||||
*/
|
||||
public void dynamicReduction() {
|
||||
//求出所有的节点ID
|
||||
List<String> nodeIds = gatewayNodeIdCache.get();
|
||||
|
||||
//如果节点数量小于等于1,则不执行缩容,至少保留一个节点
|
||||
if (nodeIds.size() <= 1) {
|
||||
log.info("暂无节点可删除!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//先获取所有的负载列表
|
||||
List<NodeLoadNum> ipAndLoadCounts = gatewayIpLoadCountKey.get();
|
||||
if (ipAndLoadCounts.size() <= 1) {
|
||||
log.error("负载列表为空!");
|
||||
return;
|
||||
}
|
||||
|
||||
//获取节点信息(IP)集合
|
||||
List<GatewayNodeInfo> gatewayNodeInfoList = gatewayNodeInfoCache.get();
|
||||
if (gatewayNodeInfoList.isEmpty()) {
|
||||
log.error("节点信息为空!");
|
||||
return;
|
||||
}
|
||||
|
||||
//判断哪个节点的负载小于30
|
||||
|
||||
for (GatewayNodeInfo gatewayNodeInfo : gatewayNodeInfoList) {//获取节点的IP
|
||||
String ip = gatewayNodeInfo.getPublicIpAddress();
|
||||
//获取当前循环节点的负载
|
||||
Long loadCount = ipAndLoadCounts.stream().filter(ipAndLoadCount -> ipAndLoadCount.getIpName().equals(ip)).findFirst().get().getLoadNum();
|
||||
//判断节点的负载是否小于30
|
||||
if (loadCount < 30) {
|
||||
//对这个节点进行缩容
|
||||
String instanceId = gatewayNodeInfo.getInstanceId();
|
||||
try {
|
||||
aliYunEcsService.releaseInstances(instanceId);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("节点缩容失败!" + e.getMessage());
|
||||
}
|
||||
log.info("节点缩容成功");
|
||||
//一次只删除一个节点
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -2,22 +2,41 @@ package com.loadCenter.aliyun.service.impl;
|
|||
|
||||
|
||||
import com.loadCenter.aliyun.common.aliyun.config.Result;
|
||||
import com.loadCenter.aliyun.gateway.cache.GatewayOrderCache;
|
||||
import com.loadCenter.aliyun.gateway.model.GatewayNodeInfo;
|
||||
import com.loadCenter.aliyun.handle.HandleCache;
|
||||
import com.loadCenter.aliyun.service.GatewayLoadService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class GatewayLoadServiceImpl implements GatewayLoadService {
|
||||
private final Long nodeLength = 100L;
|
||||
|
||||
/**
|
||||
* 负载节点列表
|
||||
*/
|
||||
private final HandleCache handleCache;
|
||||
|
||||
/**
|
||||
* 负载节点信息列表
|
||||
*/
|
||||
private final GatewayOrderCache gatewayOrderCache;
|
||||
|
||||
/**
|
||||
* 获取负载节点的IP序列列表,并返回最后一个IP进行返回
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Result<String> getAssignedServer() {
|
||||
handleCache.getLoadNodeOrderListByIpAndWeights();
|
||||
|
||||
List<String> nodeOrderList = gatewayOrderCache.get();
|
||||
String result = nodeOrderList.get(nodeOrderList.size() - 1);
|
||||
|
||||
return null;
|
||||
return Result.success(result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
com.loadCenter.aliyun.common.redis.configure.RedisConfig
|
||||
com.loadCenter.aliyun.common.redis.service.RedisService
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
# Tomcat
|
||||
server:
|
||||
port: 9010
|
||||
Spring:
|
||||
redis:
|
||||
host: 10.10.25.3
|
||||
# host: 127.0.0.1
|
||||
# host: 127.0.0.1
|
||||
port: 6379
|
||||
password: fffdev
|
||||
|
||||
|
|
Loading…
Reference in New Issue