master
31353 2024-04-21 19:38:50 +08:00
parent a889cd9388
commit 9803ea2248
12 changed files with 255 additions and 129 deletions

46
.idea/.gitignore vendored 100644
View File

@ -0,0 +1,46 @@
######################################################################
# Build Tools
.gradle
/build/
!gradle/wrapper/gradle-wrapper.jar
target/
!.mvn/wrapper/maven-wrapper.jar
######################################################################
# IDE
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### JRebel ###
rebel.xml
### NetBeans ###
nbproject/private/
build/*
nbbuild/
dist/
nbdist/
.nb-gradle/
######################################################################
# Others
*.log
*.xml.versionsBackup
*.swp
!*/build/*.java
!*/build/*.html
!*/build/*.xml

View File

@ -97,8 +97,8 @@ public class ALYunEcsService {
/**
* ID
* @param ecsSelectModel
* @return
* @param ecsSelectModel
* @return InstanceInfo
*/
public InstanceInfo selectInstanceId(EcsSelectModel ecsSelectModel) {
@ -165,44 +165,6 @@ public class ALYunEcsService {
return new InstanceInfo();
}
public List<InstanceInfo> selectInstance(EcsSelectModel ecsSelectModel) throws Exception {
List<InstanceInfo> instan = new ArrayList<>();
// 1. 初始化配置
Config config = new Config();
// 您的AccessKey ID
config.accessKeyId = aliConfig.getAccessKeyId();
// 您的AccessKey Secret
config.accessKeySecret = aliConfig.getAccessKeySecret();
//设置请求地址
config.endpoint = aliConfig.getEndpoint();
// 设置连接超时为5000毫秒
config.connectTimeout = 5000;
// 设置读超时为5000毫秒
config.readTimeout = 5000;
// 2. 初始化客户端
Client client = new Client(config);
java.util.List<String> regionIds = com.aliyun.darabonbastring.Client.split(ecsSelectModel.getInstanceIdList().toString(), ",", 50);
for (String regionId : regionIds) {
DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest()
.setPageSize(100)
.setRegionId(regionId);
DescribeInstancesResponse resp = client.describeInstances(describeInstancesRequest);
java.util.List<DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance> instances = resp.body.instances.instance;
com.aliyun.teaconsole.Client.log("" + regionId + " 下 ECS 实例列表:");
for (DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance instance : instances) {
InstanceInfo instanceInfo = new InstanceInfo();
instanceInfo.setInstanceId(instance.getInstanceId());
instanceInfo.setInstanceName(instance.getInstanceName());
instanceInfo.setPublicIpAddress(instance.getPublicIpAddress().toString());
instanceInfo.setPrivateIpAddress(instance.getVpcAttributes().getPrivateIpAddress().toString());
instan.add(instanceInfo);
com.aliyun.teaconsole.Client.log(" " + instance.hostName + " 实例ID " + instance.instanceId + " CPU:" + instance.cpu + " 内存:" + instance.memory + " MB 规格:" + instance.instanceType + " 系统:" + instance.OSType + "(" + instance.OSName + ") 状态:" + instance.status + "");
}
}
return instan;
}
/**
*
* @throws Exception
@ -245,11 +207,11 @@ public class ALYunEcsService {
String instanceChargeType = aliConfig.getInstanceChargeType();
// 创建 【1台】 实例
if (isNull == null){
String instances = RunInstance(client, regionId, imageId, instanceType, securityGroupId, vSwitchId, internetMaxBandwidthOut, internetChargeType, size, category, instanceChargeType);
String instances = runInstance(client, regionId, imageId, instanceType, securityGroupId, vSwitchId, internetMaxBandwidthOut, internetChargeType, size, category, instanceChargeType);
return instances; //返回实例ID
}
// 批量创建实例
String instances = RunInstances(client, regionId, imageId, instanceType, securityGroupId, vSwitchId, internetMaxBandwidthOut, internetChargeType, size, category, instanceChargeType);
String instances = runInstances(client, regionId, imageId, instanceType, securityGroupId, vSwitchId, internetMaxBandwidthOut, internetChargeType, size, category, instanceChargeType);
//返回实例ID
return instances;
}
@ -260,7 +222,7 @@ public class ALYunEcsService {
* RunInstances ECS
* RunInstancesECSDescribeRecommendInstanceTypeECS
*/
public String RunInstances(Client client, String regionId, String imageId, String instanceType, String securityGroupId, String vSwitchId, Integer internetMaxBandwidthOut, String internetChargeType, String size, String category, String instanceChargeType) throws Exception {
public String runInstances(Client client, String regionId, String imageId, String instanceType, String securityGroupId, String vSwitchId, Integer internetMaxBandwidthOut, String internetChargeType, String size, String category, String instanceChargeType) throws Exception {
System.setOut(new java.io.PrintStream(System.out, true, "UTF-8"));
RunInstancesRequest request1 = new RunInstancesRequest()
.setRegionId(regionId)
@ -303,7 +265,7 @@ public class ALYunEcsService {
* RunInstances ECS
* RunInstancesECSDescribeRecommendInstanceTypeECS
*/
public String RunInstance(Client client, String regionId, String imageId, String instanceType, String securityGroupId, String vSwitchId, Integer internetMaxBandwidthOut, String internetChargeType, String size, String category, String instanceChargeType) throws Exception {
public String runInstance(Client client, String regionId, String imageId, String instanceType, String securityGroupId, String vSwitchId, Integer internetMaxBandwidthOut, String internetChargeType, String size, String category, String instanceChargeType) throws Exception {
System.setOut(new java.io.PrintStream(System.out, true, "UTF-8"));
RunInstancesRequest request1 = new RunInstancesRequest()
.setRegionId(regionId)
@ -341,79 +303,46 @@ public class ALYunEcsService {
}
public DescribeInstancesResponse DescribeInstances(Client client, String regionId, String instanceIds, String instanceName) throws Exception {
DescribeInstancesRequest req = new DescribeInstancesRequest()
.setRegionId(regionId)
.setInstanceName(instanceName);
if (!com.aliyun.teautil.Common.empty(instanceIds)) {
req.instanceIds = JSON.toJSONString(com.aliyun.darabonbastring.Client.split(instanceIds, ",", 50));
/**
* ID
* @param instanceIds ID
* @throws Exception
*/
public void deleServerCreateAn(String instanceIds) throws Exception {
// 获取区域ID
String regionId = aliConfig.getRegionId();
// 如果实例ID为空则直接返回
if (com.aliyun.teautil.Common.empty(instanceIds)) {
log.info("--------------------实例ID为空无有效实例可删除--------------------");
return;
}
DescribeInstancesResponse resp = client.describeInstances(req);
log.error("--------------------查询需要删除的实例--------------------");
return resp;
// 删除实例
deleteInstances(client, regionId, instanceIds);
}
public void ModifyInstanceAttribute(Client client, String instatnceId) throws Exception {
ModifyInstanceAttributeRequest req = new ModifyInstanceAttributeRequest()
.setInstanceId(instatnceId)
.setDeletionProtection(false);
client.modifyInstanceAttribute(req);
log.info("--------------------" + instatnceId + "释放保护取消成功--------------------");
}
public void DeleteInstances(Client client, String regionId, String instanceIds, String force) throws Exception {
/**
*
* @param client
* @param regionId ID
* @param instanceIds ID
* @throws Exception
*/
private void deleteInstances(Client client, String regionId, String instanceIds) throws Exception {
// 创建删除实例请求
DeleteInstancesRequest req = new DeleteInstancesRequest()
.setRegionId(regionId)
.setInstanceId(com.aliyun.darabonbastring.Client.split(instanceIds, ",", 50))
.setForce(com.aliyun.teautil.Common.equalString(force, "true"));
.setInstanceId(com.aliyun.darabonbastring.Client.split(instanceIds, ",", 50));
// 发送删除实例请求
DeleteInstancesResponse resp = client.deleteInstances(req);
// 打印删除结果
log.info("--------------------实例释放成功--------------------");
log.info(JSON.toJSONString(com.aliyun.teautil.Common.toMap(resp)));
}
/**
*
* @param
* @throws Exception
*/
public void DeleServerCreateAn(EscRemoveModel escRemoveModel) throws Exception {
// 区域ID
//String regionId = "cn-shanghai";
String regionId = aliConfig.getRegionId();
// 多个实例ID用英文逗号分隔
//String instanceIds = "i-uf6h4s0jtpvobykd7vzc";
String instanceIds = escRemoveModel.getInstanceIds();
// 实例名称,支持使用通配符*进行模糊搜索
//String instanceName = "MyFirstEcsInstance";
String instanceName = escRemoveModel.getInstanceName();
// 强制删除有删除保护的机器
//String deleteProtected = "true";
String deleteProtected = "true";
// 强制删除运行中的机器
//String force = "true";
String force = "true";
if (com.aliyun.teautil.Common.equalString(deleteProtected, force)) {
DescribeInstancesResponse describeInstancesResp = DescribeInstances(client, regionId, instanceIds, instanceName);
instanceIds = "";
for (DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance instance : describeInstancesResp.body.instances.instance) {
instanceIds = "" + instance.instanceId + "," + instanceIds + "";
if (instance.deletionProtection) {
ModifyInstanceAttribute(client, instance.instanceId);
}
}
instanceIds = com.aliyun.darabonbastring.Client.subString(instanceIds, 0, -1);
}
if (com.aliyun.teautil.Common.empty(instanceIds)) {
log.info("--------------------无有效实例可删除--------------------");
return ;
}
DeleteInstances(client, regionId, instanceIds, force);
}

View File

@ -17,8 +17,14 @@ import org.springframework.context.annotation.Configuration;
@ConfigurationProperties(prefix = "aliyun")
public class AliConfig {
/**
* 访
*/
private String accessKeyId;
/**
* API
*/
private String accessKeySecret;
/**
@ -76,6 +82,12 @@ public class AliConfig {
*/
private String endpoint;
/**
* Client Spring
* @param aliConfig
* @return client
* @throws Exception
*/
@Bean
public Client createClient(AliConfig aliConfig) throws Exception {
// 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。

View File

@ -57,6 +57,16 @@ public class Constans {
*/
public final static Long NUMERICAL_VALUE_LONG_ZERO = 0L;
/**
*
*/
public final static Boolean IS_BOOLEAN_METHOD_FALSE= false;
/**
*
*/
public final static Boolean IS_BOOLEAN_METHOD_TRUE= true;
}

View File

@ -0,0 +1,18 @@
package com.guo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author gxb
* @description RESTfulHTTP
* @date 2024-04-15 17:20
*/
@Configuration
public class RestClientConfig {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}

View File

@ -18,7 +18,8 @@ public class GateWayController {
private GateWayLoadService gateWayLoadService;
/**
*
* 线
* @param VehicleVIN VIN
* @return IP
*/
@PostMapping("/load/node/{VehicleVIN}")
@ -27,4 +28,12 @@ public class GateWayController {
return Result.success(gateWayLoadService.loadNode(VehicleVIN));
}
/**
* 线
* @param VehicleVIN VIN
*/
@PostMapping("/vehicle/removal/{VehicleVIN}")
public void vehicleRemoval(@PathVariable("VehicleVIN") String VehicleVIN){
gateWayLoadService.vehicleRemoval(VehicleVIN);
}
}

View File

@ -8,7 +8,8 @@ package com.guo.service.impl;
public interface GateWayLoadService {
/**
*
* 线
* @param VehicleVIN VIN
* @return IP
*/
String loadNode(String VehicleVIN);
@ -18,4 +19,9 @@ public interface GateWayLoadService {
*/
void refreshLoad();
/**
* 线
* @param vehicleVIN VIN
*/
void vehicleRemoval(String vehicleVIN);
}

View File

@ -1,5 +1,7 @@
package com.guo.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.guo.common.constant.LoadConstants;
import com.guo.gateway.cache.*;
import com.guo.gateway.model.NodeInfo;
@ -12,6 +14,7 @@ import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* @author gxb
@ -73,11 +76,15 @@ public class GateWayLoadServicelmpl implements GateWayLoadService {
Long seriesLoadIndex = seriesLoad % LoadConstants.NODE_LENGTH;
//获取负载下标通过获取节点ID
String loadNodeId = loadNodeCache.getFindByIndex(seriesLoadIndex);
//存储 key:实例ID value:VIN
NodeVehicle nodeVehicle = new NodeVehicle();
nodeVehicle.setNodeId(loadNodeId);
nodeVehicle.setVehicleVin(VehicleVIN);
//存入车辆VIN 和 节点ID
vehicleLineNodeCache.save(nodeVehicle);
//存入车辆信息 key车辆VIN 值nodeVehicle
nodeSetVinCache.put(nodeVehicle);
//获取缓存内节点的公网/内网信息
NodeInfo nodeInfo = nodeCache.get(loadNodeId);
// 返回公网IP
@ -117,11 +124,6 @@ public class GateWayLoadServicelmpl implements GateWayLoadService {
.build())
.toList();
System.out.println(workGatewayNodes);
System.out.println(workGatewayNodeWeight);
List<String> loadNodeList = new ArrayList<>();
int count = workGatewayNodeWeight.stream().mapToInt(WorkGatewayNode::getWeight).sum();
@ -169,6 +171,34 @@ public class GateWayLoadServicelmpl implements GateWayLoadService {
// refreshLoadLock.unlock();
//}
/**
* 线
* @param vehicleVIN VIN
*/
@Override
public void vehicleRemoval(String vehicleVIN) {
//对应节点下的车辆VIN剔除
String nodeVehicleString = nodeSetVinCache.get(vehicleVIN);
NodeVehicle nodeVehicle = JSONObject.parseObject(nodeVehicleString, NodeVehicle.class);
//节点ID
String nodeId = nodeVehicle.getNodeId();
//获取车辆VIN集合
Set<String> vinSetList = vehicleLineNodeCache.get(nodeId);
//剔除掉下线的车辆VIN
for (String vin : vinSetList) {
if (!vehicleVIN.equals(vin)){
NodeVehicle Vehicle = new NodeVehicle();
Vehicle.setNodeId(nodeId);
Vehicle.setVehicleVin(vin);
//存入车辆VIN 和 节点ID
vehicleLineNodeCache.save(nodeVehicle);
}
}
}
/**
* ECS
*/

View File

@ -19,6 +19,7 @@ import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
@ -26,10 +27,11 @@ import java.util.List;
/**
* @author gxb
* @description
* @description
* @date 2024-04-18 19:01
*/
@Component
@Service
@Log4j2
@AllArgsConstructor
public class Collection {
@ -150,7 +152,7 @@ public class Collection {
nodeJoin.setLinkingNumber(Long.valueOf(connectSize));
nodeScoreCache.save(nodeJoin);
//加层判断,把不满足缩容条件的缓存删除 连接数 > 最低阈值
//判断,把不满足缩容条件的缓存删除 连接数 > 最低阈值 且 记录过
if (connectSize > beforemaxNumber && nodeReduced.isWhether(instance.getInstanceId())) {
nodeReduced.remove(instance.getInstanceId());
}
@ -172,7 +174,11 @@ public class Collection {
}
/**
*
* @param publicIPaddress IP
* @return int
*/
public int querymqttConnections(String publicIPaddress){
//获取每个FluxMQ运行信息

View File

@ -1,21 +1,31 @@
package com.guo.task.Contraction;
import com.guo.aly.ALYunEcsService;
import com.guo.aly.model.EscRemoveModel;
import com.guo.common.constant.Constans;
import com.guo.common.constant.LoadConstants;
import com.guo.common.domain.Result;
import com.guo.common.model.TotalNumber;
import com.guo.config.RestClientConfig;
import com.guo.gateway.cache.NodeReduced;
import com.guo.gateway.cache.NodeScoreCache;
import com.guo.gateway.cache.VehicleLineNodeCache;
import com.guo.gateway.model.NodeJoin;
import com.guo.gateway.model.WorkGatewayNode;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* @author gxb
* @description
* @description
* @date 2024-04-18 19:52
*/
@AllArgsConstructor
@ -28,6 +38,10 @@ public class ContractionVolume {
*/
private final VehicleLineNodeCache vehicleLineNodeCache;
/**
*
*/
private final NodeScoreCache nodeScoreCache;
/**
* 5
*/
@ -36,6 +50,9 @@ public class ContractionVolume {
@Autowired
private ALYunEcsService alYunEcsService;
@Autowired
private RestTemplate restTemplate;
/**
*
*/
@ -43,9 +60,9 @@ public class ContractionVolume {
/**
*
* @param nodeId
* @param nodeId ID
*/
public void reduction(String nodeId){
public void reduction(String nodeId) throws Exception {
//非空判断
if (null != nodeId){
//判断是否被标记过
@ -59,16 +76,52 @@ public class ContractionVolume {
//比较 剩余时间 小于5分钟
if (expire < fiveMinutesSeconds){
//默认false
boolean flag = Constans.IS_BOOLEAN_METHOD_FALSE;
//根据节点ID获取缓存内的车辆VIN值
Set<String> vehicleVinSetList = vehicleLineNodeCache.get(nodeId);
//判断是否存在车辆信息
if (!vehicleVinSetList.isEmpty()){
//执行下线
for (String vehicleVin : vehicleVinSetList) {
//通过RestTemplate发送http请求车辆下线操作 选择要释放节点下的车辆信息
String url = "http://127.0.0.1:81/vehicle/instance/client/close/"+vehicleVin;
//响应
restTemplate.postForObject(url, null, Result.class);
}
flag = Constans.IS_BOOLEAN_METHOD_TRUE;
}
//删除节点 释放
alYunEcsService.deleServerCreateAn(nodeId);
//删除节点信息
//刷新连接数和IP地址
List<WorkGatewayNode> workGatewayNodes = nodeScoreCache.getNodeScore();
for (WorkGatewayNode workGatewayNode : workGatewayNodes) {
if (!nodeId.equals(workGatewayNode.getNodeId())){
NodeJoin nodeJoin = new NodeJoin();
nodeJoin.setNodeId(workGatewayNode.getNodeId());
nodeJoin.setLinkingNumber(Long.valueOf(String.valueOf(workGatewayNode.getWeight())));
nodeScoreCache.save(nodeJoin);
}
}
//车辆上线
if (flag){
//执行重新下线
for (String vehicleVin : vehicleVinSetList) {
//通过RestTemplate发送http请求车辆上线操作 选择要释放节点下的车辆信息
String url = "http://127.0.0.1:81/vehicle/instance/client/init/" + vehicleVin;
restTemplate.postForObject(url, null, Result.class);
}
}
}
}
//记录
@ -79,7 +132,7 @@ public class ContractionVolume {
/**
*
* @param totalNumber
* @param totalNumber -
*/
public void contractionVolume(TotalNumber totalNumber){
//特殊情况 无节点
@ -88,7 +141,8 @@ public class ContractionVolume {
log.error("当前未存在节点信息");
try {
//创建实例方法 【2台】
//alYunEcsService.createAnServer(LoadConstants.IS_NULL);
alYunEcsService.createAnServer(null);
Thread.sleep(5000);
} catch (Exception e) {
log.error("扩容失败!!!!!");
e.printStackTrace();
@ -98,13 +152,17 @@ public class ContractionVolume {
}
//调用计算
Long value = this.percentage(totalNumber);
log.info("当前节点负载率:" + value + "%");
//判断达到60%
if (value >= LoadConstants.INTERMEDIATE && value < LoadConstants.MAXIMUM){
//当节点负载达到 60%时,调用扩容一台方法
log.info("Node 节点负载达到 " + value + "%,达到扩容一台的条件☑");
try {
//创建实例方法 【1台】
//alYunEcsService.createAnServer(null);
alYunEcsService.createAnServer(null);
Thread.sleep(5000);
} catch (Exception e) {
log.error("扩容失败!!!!!");
e.printStackTrace();
@ -117,6 +175,7 @@ public class ContractionVolume {
try {
//创建实例方法 【2台】
// alYunEcsService.createAnServer(LoadConstants.IS_NULL);
Thread.sleep(5000);
} catch (Exception e) {
log.error("扩容失败!!!!!");
e.printStackTrace();
@ -126,21 +185,21 @@ public class ContractionVolume {
}
/**
*
*
*/
private Long percentage(TotalNumber totalNumber){
//获取节点数量
Long nodeNumber = totalNumber.getNodeNumber();
//根据nodeNumber去获取最大节点数 默认 100
Long sumNodeNumber = nodeNumber * LoadConstants.MAX_NUMBER;
//根据nodeNumber去获取最大节点数 默认 80
Long sumNodeNumber = nodeNumber * LoadConstants.MAXIMUM;
//获取节点连接总数
Long connectionTotal = totalNumber.getConnectionTotal();
//计算空余连接数
// Long vacantNumber = sumNodeNumber - connectionTotal;
//计算当前负载情况
//计算当前负载情况 连接总数 / 最大连接数
double loadPercentage = (double)connectionTotal / sumNodeNumber;
//进行四舍五入取整
long roundLoadPercentage = Math.round(loadPercentage) * LoadConstants.BE_COMMON;
long roundLoadPercentage = Math.round(loadPercentage * LoadConstants.BE_COMMON);
//返回百分比
return roundLoadPercentage;
}

View File

@ -7,6 +7,7 @@ spring:
host: 127.0.0.1
port: 6379
# 阿里云配置
aliyun:
accessKeyId: LTAI5tPDLpTbAX9bUSrTSrPH
accessKeySecret: rbLG6bh8ZSttUPMxUspk9j8XLzvLU0