From b85e8795da00cde5da88b49e5481415caed43145 Mon Sep 17 00:00:00 2001 From: JangCan <2862008188@qq.com> Date: Sat, 20 Apr 2024 09:29:29 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E8=8E=B7=E5=8F=96=E5=AE=9E=E4=BE=8B?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aliyun/service/AliYunEcsService.java | 128 +++++++++++++----- .../service/impl/GatewayLoadServiceImpl.java | 28 +++- 2 files changed, 121 insertions(+), 35 deletions(-) diff --git a/src/main/java/com/loadcenter/common/aliyun/service/AliYunEcsService.java b/src/main/java/com/loadcenter/common/aliyun/service/AliYunEcsService.java index 18bd1de..9a62039 100644 --- a/src/main/java/com/loadcenter/common/aliyun/service/AliYunEcsService.java +++ b/src/main/java/com/loadcenter/common/aliyun/service/AliYunEcsService.java @@ -1,4 +1,5 @@ package com.loadcenter.common.aliyun.service; + import com.alibaba.fastjson2.JSON; import com.aliyun.ecs20140526.Client; import com.aliyun.ecs20140526.models.*; @@ -13,16 +14,17 @@ import com.loadcenter.common.utils.user.UserUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; + import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; /** - * @ClassName AliYunEcsService - * @Description 阿里云ecs服务器openAPI调用 - * @Author Can.J - * @Date 2024/4/16 + * @ClassName AliYunEcsService + * @Description 阿里云ecs服务器openAPI调用 + * @Author Can.J + * @Date 2024/4/16 */ @Component @Slf4j @@ -33,7 +35,6 @@ public class AliYunEcsService { @Autowired private InstanceSpecification instanceSpecification; - //应用阿里云客户端配置 private final AliConfig aliConfig; private final Client client; @@ -51,6 +52,7 @@ public class AliYunEcsService { /** * 获取指定区域的实例ID列表 + * * @return * @throws Exception */ @@ -89,6 +91,7 @@ public class AliYunEcsService { /** * 通过实例ID释放实例 多个实例ID,用英文逗号分隔 + * * @param instanceIds * @throws Exception */ @@ -124,6 +127,7 @@ public class AliYunEcsService { /** * 查询要删除的实例 + * * @param client * @param regionId * @param instanceIds @@ -146,6 +150,7 @@ public class AliYunEcsService { /** * 修改实例的属性 取消 ‘释放保护’ + * * @param client * @param instatnceId * @throws Exception @@ -160,6 +165,7 @@ public class AliYunEcsService { /** * 执行释放实例 + * * @param client * @param regionId * @param instanceIds @@ -178,6 +184,7 @@ public class AliYunEcsService { /** * 创建并运行实例 + * * @return * @throws Exception */ @@ -210,41 +217,26 @@ public class AliYunEcsService { String instanceChargeType = instanceSpecification.getInstanceChargeType(); // 批量创建实例 - return RunInstances(client, regionId, imageId, instanceType, securityGroupId, vSwitchId, internetMaxBandwidthOut, internetChargeType, size, category, instanceChargeType); + return RunInstances(); } /** - * RunInstances * 通过备选实例规格创建ECS实例最佳实践 - * 该场景中,在调用RunInstances创建ECS实例时判断是否发生库存不足等错误, - * 如果发生错误,将调用DescribeRecommendInstanceType查询备选实例, - * 然后通过备选实例规格重新创建ECS实例。 - * @param client - * @param regionId - * @param imageId - * @param instanceType - * @param securityGroupId - * @param vSwitchId - * @param internetMaxBandwidthOut - * @param internetChargeType - * @param size - * @param category - * @param instanceChargeType * @return * @throws Exception */ - public static 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() throws Exception { RunInstancesRequest request = new RunInstancesRequest() - .setRegionId(regionId) - .setImageId(imageId) - .setInstanceType(instanceType) - .setSecurityGroupId(securityGroupId) - .setVSwitchId(vSwitchId) + .setRegionId(aliConfig.getRegionId()) + .setImageId(instanceSpecification.getImageId()) + .setInstanceType(instanceSpecification.getInstanceType()) + .setSecurityGroupId(instanceSpecification.getSecurityGroupId()) + .setVSwitchId(instanceSpecification.getVSwitchId()) .setInstanceName("自动创建的实例节点") .setDescription(new Date().toLocaleString() + " 创建的实例节点") - .setInternetMaxBandwidthOut(internetMaxBandwidthOut) - .setInternetChargeType(internetChargeType) - .setInstanceChargeType(instanceChargeType) + .setInternetMaxBandwidthOut(Integer.valueOf(instanceSpecification.getInternetMaxBandwidthOut())) + .setInternetChargeType(instanceSpecification.getInternetChargeType()) + .setInstanceChargeType(instanceSpecification.getInstanceChargeType()) // 批量创建五台ECS实例,如果不设置该参数,默认创建一台ECS实例。 // amount = 5, // 如果缺少库存可以接受的最低创建数量。 @@ -254,8 +246,8 @@ public class AliYunEcsService { // .setDryRun(true) .setDryRun(false) .setSystemDisk(new RunInstancesRequest.RunInstancesRequestSystemDisk() - .setSize(size) - .setCategory(category)); + .setSize(instanceSpecification.getSize()) + .setCategory(instanceSpecification.getCategory())); String result = ""; @@ -277,6 +269,7 @@ public class AliYunEcsService { /** * 查询一台或多台实例的信息 多台实例用英文逗号拼接 + * * @param instanceIds * @return * @throws Exception @@ -364,4 +357,75 @@ public class AliYunEcsService { } return instances; } + + /** + * 传入实例ID + */ + public InstancesInformation selectList(String instanceId) throws Exception { + + DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest() + .setRegionId(aliConfig.getRegionId()) + .setInstanceName("*") + .setInstanceIds(com.aliyun.teautil.Common.toJSONString(com.aliyun.darabonbastring.Client.split(instanceId, ",", 50))) + .setPageSize(10); + + + //初始化返回值 + List instanceList = null; + + + try { + + // 复制代码运行请自行打印 API 的返回值 + DescribeInstancesResponse describeInstancesResponse = client.describeInstancesWithOptions(describeInstancesRequest, new RuntimeOptions()); + DescribeInstancesResponseBody body = describeInstancesResponse.getBody(); + DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstances instances = body.getInstances(); + + instanceList = instances.getInstance(); + + if (instanceList == null || instanceList.isEmpty()){ + return new InstancesInformation(); + } + + + InstancesInformation ecsInstanceInfo = new InstancesInformation(); + instanceList.forEach(item -> { + + ecsInstanceInfo.setInstanceName(item.getInstanceName()); + + ecsInstanceInfo.setInstanceId(item.getInstanceId()); + + ecsInstanceInfo.setStatus(item.status); + + ecsInstanceInfo.setPublicIpAddress(UserUtil.removeBrackets(item.getPublicIpAddress().getIpAddress().toString())); + + ecsInstanceInfo.setRecyclable(item.getRecyclable()); + + ecsInstanceInfo.setPrivateIpAddress(item.getVpcAttributes().getPrivateIpAddress().ipAddress.toString()); + + }); + return ecsInstanceInfo; + + } catch (TeaException error) { + log.error("code:[{}], message: [{}],data: [{}]",error.getCode(),error.getMessage(),error.getData()); + // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。 + // 错误 message + System.out.println(error.getMessage()); + // 诊断地址 + System.out.println(error.getData().get("Recommend")); + com.aliyun.teautil.Common.assertAsString(error.message); + } catch (Exception _error) { + TeaException error = new TeaException(_error.getMessage(), _error); + + log.error("message: [{}]",_error.getMessage(),_error); + // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。 + // 错误 message + System.out.println(error.getMessage()); + // 诊断地址 + System.out.println(error.getData().get("Recommend")); + com.aliyun.teautil.Common.assertAsString(error.message); + } + + return new InstancesInformation(); + } } diff --git a/src/main/java/com/loadcenter/service/impl/GatewayLoadServiceImpl.java b/src/main/java/com/loadcenter/service/impl/GatewayLoadServiceImpl.java index f1f3015..dd575d9 100644 --- a/src/main/java/com/loadcenter/service/impl/GatewayLoadServiceImpl.java +++ b/src/main/java/com/loadcenter/service/impl/GatewayLoadServiceImpl.java @@ -2,6 +2,8 @@ package com.loadcenter.service.impl; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; +import com.loadcenter.common.aliyun.service.AliYunEcsService; +import com.loadcenter.common.domain.InstancesInformation; import com.loadcenter.gateway.cache.*; import com.loadcenter.gateway.model.GatewayNodeInfo; import com.loadcenter.gateway.model.WorkGatewayNode; @@ -12,6 +14,7 @@ import lombok.extern.slf4j.Slf4j; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.IOException; @@ -54,6 +57,9 @@ public class GatewayLoadServiceImpl implements GatewayLoadService { private final GatewayNodeScoreCache gatewayNodeScoreCache; + @Autowired + private AliYunEcsService aliYunEcsService; + /** * 负载节点 * @@ -183,16 +189,32 @@ public class GatewayLoadServiceImpl implements GatewayLoadService { /** * 动态ECS */ - public void dynamicEcs(){ + public void dynamicEcs() throws Exception { //上线最大数量 Long vehicleMaxOnlineNum = gatewayNodeScoreCache.getNodeMaxOnlineNum(); //当前连接数 Long vehicleOnlineNowNum = gatewayNodeScoreCache.getNodeNowNum(); BigDecimal loadRate = new BigDecimal(vehicleMaxOnlineNum).divide(new BigDecimal(vehicleOnlineNowNum), 0, BigDecimal.ROUND_HALF_UP); - - if(loadRate.longValue()>80){ + log.info("负载率:[{}]",loadRate); + if(loadRate.longValue()>=80L){ //调用扩容逻辑 + log.info("负载过高,开始扩容"); + String instanceId = aliYunEcsService.RunInstances(); + + log.info("扩容的节点是:[{}]",instanceId); + + //休眠5秒确保新实例创建完成 + Thread.sleep(5000); + + //获取新实例信息放入redis + InstancesInformation instancesInformation = aliYunEcsService.selectList(instanceId); + + GatewayNodeInfo gatewayNodeInfo = new GatewayNodeInfo(); + gatewayNodeInfo.setNodeId(instancesInformation.getInstanceId()); + gatewayNodeInfo.setPublicAddress(instancesInformation.getPublicIpAddress()); + gatewayNodeInfo.setPrivateAddress(instancesInformation.getPrivateIpAddress()); + }else if (loadRate.longValue()<20){ //调用缩容逻辑 }