421
parent
7dc1077935
commit
ad7bba6679
8
pom.xml
8
pom.xml
|
@ -7,7 +7,13 @@
|
|||
<groupId>com.muyu</groupId>
|
||||
<artifactId>LoadCenter</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>aliyundeveloper</id>
|
||||
<name>Aliyun SDK</name>
|
||||
<email>aliyunsdk@aliyun.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
|
|
|
@ -37,21 +37,32 @@ public class ALYunEcsService {
|
|||
|
||||
/**
|
||||
* 根据实例ID和实例名称查询实例信息
|
||||
* @param instanceName
|
||||
* @param ecsSelectModel
|
||||
* @return 返回实例集合信息
|
||||
*/
|
||||
public List<InstanceInfo> selectECS(String instanceName) throws Exception {
|
||||
|
||||
public List<InstanceInfo> selectECS(EcsSelectModel ecsSelectModel) throws Exception {
|
||||
DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest()
|
||||
.setRegionId(aliConfig.getRegionId())
|
||||
.setInstanceName(instanceName)
|
||||
.setPageSize(10);
|
||||
|
||||
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
|
||||
// 判断是否指定了实例ID或实例名称
|
||||
if (ecsSelectModel.getInstanceIdList() != null && !ecsSelectModel.getInstanceIdList().isEmpty()) {
|
||||
// 如果指定了实例ID,则设置实例ID查询条件
|
||||
describeInstancesRequest.setInstanceIds(String.join(",", ecsSelectModel.getInstanceIdList()));
|
||||
} else if (ecsSelectModel.getInstanceNameList() != null && !ecsSelectModel.getInstanceNameList().isEmpty()) {
|
||||
// 如果指定了实例名称,则设置实例名称查询条件
|
||||
describeInstancesRequest.setInstanceName(String.join(",", ecsSelectModel.getInstanceNameList()));
|
||||
} else {
|
||||
// 如果既没有指定实例ID也没有指定实例名称,则抛出异常或者返回空列表,视情况而定
|
||||
throw new IllegalArgumentException("Please provide at least one instance ID or instance name.");
|
||||
// 或者直接返回空列表
|
||||
// return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<InstanceInfo> instanceInfos = new ArrayList<>(); // 用于存储查询到的实例信息
|
||||
|
||||
try {
|
||||
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
|
||||
DescribeInstancesResponse describeInstancesResponse = client.describeInstancesWithOptions(describeInstancesRequest, runtime);
|
||||
DescribeInstancesResponseBody body = describeInstancesResponse.getBody();
|
||||
DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstances instances = body.getInstances();
|
||||
|
@ -66,7 +77,7 @@ public class ALYunEcsService {
|
|||
// 去掉方括号
|
||||
publicIpAddress = publicIpAddress.substring(1, publicIpAddress.length() - 1);
|
||||
instanceInfo.setPublicIpAddress(publicIpAddress);
|
||||
String privateIpAddress = item.getVpcAttributes().getPrivateIpAddress().ipAddress.toString();
|
||||
String privateIpAddress = item.getVpcAttributes().getPrivateIpAddress().getIpAddress().toString();
|
||||
// 去掉方括号
|
||||
privateIpAddress = privateIpAddress.substring(1, privateIpAddress.length() - 1);
|
||||
instanceInfo.setPrivateIpAddress(privateIpAddress);
|
||||
|
@ -74,9 +85,13 @@ public class ALYunEcsService {
|
|||
}
|
||||
} catch (TeaException error) {
|
||||
error.printStackTrace();
|
||||
// 可以打印错误信息以便排查问题
|
||||
System.out.println("TeaException occurred: " + error.getMessage());
|
||||
// 异常处理
|
||||
} catch (Exception _error) {
|
||||
_error.printStackTrace();
|
||||
// 可以打印错误信息以便排查问题
|
||||
System.out.println("Exception occurred: " + _error.getMessage());
|
||||
// 异常处理
|
||||
}
|
||||
|
||||
|
@ -85,6 +100,7 @@ public class ALYunEcsService {
|
|||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 创建实例方法
|
||||
* @throws Exception
|
||||
|
|
|
@ -74,7 +74,7 @@ public class AliConfig {
|
|||
private String instanceChargeType;
|
||||
|
||||
@Bean
|
||||
public Client createClient(AliConfig aliConfig) throws Exception {
|
||||
public Client createClient(AliConfig aliConfig) throws Exception {
|
||||
// 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
|
||||
// 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378657.html。
|
||||
Config config = new Config()
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package com.muyu.common.constant;
|
||||
|
||||
/**
|
||||
* @Author: wanghao //作者
|
||||
* @CreateDate: 2024/4/21 16:06 //创建时间
|
||||
*/
|
||||
|
||||
|
||||
public class Constans {
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* http请求头部前缀
|
||||
*/
|
||||
public final static String HTTP_REQUEST_HEAD = "http://";
|
||||
|
||||
/**
|
||||
* 请求端口及路径
|
||||
*/
|
||||
public final static String HTTP_REQUEST_ADDRESS = ":8080/public/cluster";
|
||||
|
||||
/**
|
||||
* HTTP请求头的一个字段
|
||||
*/
|
||||
public final static String HTTP_REQUEST_ADDHEADER_AGENT = "User-Agent";
|
||||
|
||||
/**
|
||||
* 请求是从Apifox 1.0.0版本的客户端发起
|
||||
*/
|
||||
public final static String HTTP_REQUEST_ADDHEADER_APIFOX = "Apifox/1.0.0 (https://apifox.com)";
|
||||
|
||||
/**
|
||||
* HTTP请求头部字段,用于传递访问令牌
|
||||
*/
|
||||
public final static String HTTP_REQUEST_ADDHEADER_ACCESSTOKEN = "Accesstoken";
|
||||
|
||||
/**
|
||||
* 空字符串
|
||||
*/
|
||||
public final static String HTTP_REQUEST_NULL_STRING = "";
|
||||
|
||||
/**
|
||||
* 数值 0
|
||||
*/
|
||||
public final static Integer NUMERICAL_VALUE_ZERO = 0;
|
||||
|
||||
/**
|
||||
* 别名mqttInfo获取消息队列
|
||||
*/
|
||||
public final static String HTTP_REQUEST_MQTTINFO = "mqttInfo";
|
||||
|
||||
/**
|
||||
* 获取了 "mqttInfo" 对象中名为 "connectSize" 的整数值
|
||||
*/
|
||||
public final static String HTTP_REQUEST_CONNECTSIZE = "connectSize";
|
||||
|
||||
/**
|
||||
* 通用默认数值 0L Long
|
||||
*/
|
||||
public final static Long NUMERICAL_VALUE_LONG_ZERO = 0L;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -4,9 +4,7 @@ import com.muyu.common.domain.Result;
|
|||
import com.muyu.service.GatewayLoadService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* @Author: wanghao //作者
|
||||
|
@ -19,17 +17,20 @@ import org.springframework.web.bind.annotation.RestController;
|
|||
public class GatewayController {
|
||||
|
||||
@Autowired
|
||||
private GatewayLoadService gatewayLoadService;
|
||||
private GatewayLoadService gateWayLoadService;
|
||||
|
||||
/**
|
||||
* 获取负载节点
|
||||
* @return 返回公网IP
|
||||
*/
|
||||
@PostMapping("/load/node/{VehicleVIN}")
|
||||
public Result<String> loadNode(@PathVariable("VehicleVIN") String VehicleVIN){
|
||||
|
||||
@GetMapping("/load/node")
|
||||
public Result<String> loadNode(){
|
||||
return Result.success(gatewayLoadService.loadNode());
|
||||
return Result.success(gateWayLoadService.loadNode(VehicleVIN));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ public class LoadSeriesCache extends GatewayCacheAbs<String> {
|
|||
* @return 自增后的值
|
||||
*/
|
||||
public Long incrementAndGet(){
|
||||
return redisService.increment(encode(CacheConstants.GATEWAY_LOAD_SERIES_KEY),1L);
|
||||
return redisService.increment(encode(CacheConstants.GATEWAY_LOAD_SERIES_KEY),0L);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.muyu.gateway.cache;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.muyu.common.constant.CacheConstants;
|
||||
import com.muyu.gateway.cache.abs.GatewayCacheAbs;
|
||||
import com.muyu.gateway.model.NodeInfo;
|
||||
|
@ -35,9 +36,19 @@ public class NodeCache extends GatewayCacheAbs<String> {
|
|||
* @return 节点信息
|
||||
*/
|
||||
public NodeInfo get(String nodeId){
|
||||
return redisService.getCacheObject(encode(nodeId));
|
||||
JSONObject jsonObject = redisService.getCacheObject(encode(nodeId));
|
||||
if (jsonObject != null) {
|
||||
NodeInfo nodeInfo = new NodeInfo();
|
||||
nodeInfo.setNodeId(jsonObject.getString("nodeId"));
|
||||
nodeInfo.setPublicIdAddress(jsonObject.getString("publicIdAddress"));
|
||||
nodeInfo.setPrivateIdAddress(jsonObject.getString("privateIdAddress"));
|
||||
return nodeInfo;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除网关节点
|
||||
* @param nodeId
|
||||
|
@ -46,7 +57,6 @@ public class NodeCache extends GatewayCacheAbs<String> {
|
|||
redisService.deleteObject(encode(nodeId));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
package com.muyu.gateway.cache;
|
||||
|
||||
import com.alibaba.fastjson2.JSONException;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.muyu.common.constant.CacheConstants;
|
||||
import com.muyu.gateway.cache.abs.GatewayCacheAbs;
|
||||
import com.muyu.gateway.model.NodeJoin;
|
||||
import com.muyu.gateway.model.WorkGatewayNode;
|
||||
import org.springframework.data.redis.core.DefaultTypedTuple;
|
||||
import org.springframework.data.redis.core.ZSetOperations;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -27,39 +32,80 @@ public class NodeScoreCache extends GatewayCacheAbs<String> {
|
|||
return CacheConstants.GATEWAY_COMMON;
|
||||
}
|
||||
|
||||
public List<WorkGatewayNode> getNodeScore(){
|
||||
Set<ZSetOperations.TypedTuple<String>> range = redisService.redisTemplate.opsForZSet().rangeWithScores(encode(CacheConstants.GATEWAY_NODE_SCORE_CACHE), 0, -1);
|
||||
return range.stream()
|
||||
.map(ZSet -> WorkGatewayNode.builder().nodeId(ZSet.getValue()).weight(Integer.valueOf(String.valueOf(ZSet.getScore()))).build())
|
||||
.toList();
|
||||
/**
|
||||
* 获取连接数
|
||||
* @return
|
||||
*/
|
||||
public List<WorkGatewayNode> getNodeScore() {
|
||||
Set<ZSetOperations.TypedTuple<Object>> range = redisService
|
||||
.redisTemplate.opsForZSet()
|
||||
.rangeWithScores(encode(CacheConstants.GATEWAY_NODE_SCORE_CACHE), 0, -1);
|
||||
|
||||
if (range == null || range.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return range.stream()
|
||||
.map(tuple -> {
|
||||
|
||||
try {
|
||||
JSONObject jsonObject = (JSONObject) tuple.getValue();
|
||||
|
||||
// 从 JSONObject 中获取字段值
|
||||
String nodeId = jsonObject.getString("nodeId");
|
||||
long linkingNumber = jsonObject.getLongValue("linkingNumber");
|
||||
|
||||
NodeJoin nodeJoin = new NodeJoin();
|
||||
nodeJoin.setNodeId(nodeId);
|
||||
nodeJoin.setLinkingNumber(linkingNumber);
|
||||
|
||||
// double score = tuple.getScore(); // 获取分数
|
||||
return WorkGatewayNode.builder()
|
||||
.nodeId(nodeId)
|
||||
.weight(Integer.valueOf(String.valueOf(nodeJoin.getLinkingNumber()))) // 假设分数是double类型,这里将其转换为int类型
|
||||
.build();
|
||||
} catch (JSONException e) {
|
||||
// JSON 解析异常处理
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Objects::nonNull) // 过滤掉解析失败的节点
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取目前连接数
|
||||
* @return
|
||||
*/
|
||||
public Long getNodeNowNum(){
|
||||
List<WorkGatewayNode> workGatewayNodes = getNodeScore();
|
||||
//目前连接数
|
||||
Long vehicleOnlineNowNum= Long.valueOf(String.valueOf(
|
||||
workGatewayNodes.stream().mapToDouble(WorkGatewayNode::getWeight).sum()
|
||||
));
|
||||
// 直接将 double 类型结果转换为 Long 类型
|
||||
Long vehicleOnlineNowNum = (long) workGatewayNodes.stream()
|
||||
.mapToDouble(WorkGatewayNode::getWeight)
|
||||
.sum();
|
||||
return vehicleOnlineNowNum;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 存入节点ID及连接数
|
||||
* @param nodeJoin
|
||||
*/
|
||||
public void save(NodeJoin nodeJoin){
|
||||
redisService.setCacheSets(encode(CacheConstants.GATEWAY_NODE_SCORE_CACHE),nodeJoin);
|
||||
public void save(NodeJoin nodeJoin) {
|
||||
ZSetOperations.TypedTuple<Object> tuple = new DefaultTypedTuple<>(nodeJoin, 0.0); // 使用默认的分数为0.0
|
||||
redisService.redisTemplate.opsForZSet().add(encode(CacheConstants.GATEWAY_NODE_SCORE_CACHE), Collections.singleton(tuple));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取连接数信息
|
||||
* @return
|
||||
* 删除缓存
|
||||
*/
|
||||
public List<String> get(){
|
||||
return redisService.getCacheObject(encode(CacheConstants.GATEWAY_NODE_SCORE_CACHE));
|
||||
public void delete(){
|
||||
redisService.deleteObject(encode(CacheConstants.GATEWAY_NODE_SCORE_CACHE));
|
||||
}
|
||||
|
||||
|
||||
|
@ -72,7 +118,6 @@ public class NodeScoreCache extends GatewayCacheAbs<String> {
|
|||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -49,7 +49,6 @@ public class NodeSetVinCache extends GatewayCacheAbs<String> {
|
|||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,14 +3,13 @@ package com.muyu.service;
|
|||
public interface GatewayLoadService {
|
||||
|
||||
/**
|
||||
* 负载节点
|
||||
* @return 返回负载节点
|
||||
*
|
||||
* */
|
||||
String loadNode();
|
||||
* 获取负载节点
|
||||
* @return 返回公网IP
|
||||
*/
|
||||
String loadNode(String VehicleVIN);
|
||||
|
||||
/**
|
||||
* 刷新负载规格
|
||||
* */
|
||||
void refreshLoad();
|
||||
* 刷新负载
|
||||
*/
|
||||
void refreshLoad();
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.muyu.service.impl;
|
|||
import com.muyu.common.constant.LoadConstants;
|
||||
import com.muyu.gateway.cache.*;
|
||||
import com.muyu.gateway.model.NodeInfo;
|
||||
import com.muyu.gateway.model.NodeVehicle;
|
||||
import com.muyu.gateway.model.WorkGatewayNode;
|
||||
import com.muyu.service.GatewayLoadService;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
@ -68,17 +69,22 @@ public class GatewayLoadServiceImpl implements GatewayLoadService {
|
|||
* @return 返回公网IP
|
||||
*/
|
||||
@Override
|
||||
public String loadNode() {
|
||||
public String loadNode(String VehicleVIN) {
|
||||
//去刷新负载
|
||||
refreshLoad();
|
||||
//获取自增序列值
|
||||
Long seriesLoad = loadSeriesCache.incrementAndGet(); //获取自增序列值
|
||||
Long seriesLoadIndex = seriesLoad % LoadConstants.NODE_LENGTH;
|
||||
//获取负载下标
|
||||
//获取负载下标通过获取节点ID
|
||||
String loadNodeId = loadNodeCache.getFindByIndex(seriesLoadIndex);
|
||||
//通过获取节点ID
|
||||
//存储 key:实例ID value:VIN
|
||||
NodeVehicle nodeVehicle = new NodeVehicle();
|
||||
nodeVehicle.setNodeId(loadNodeId);
|
||||
nodeVehicle.setVehicleVin(VehicleVIN);
|
||||
vehicleLineNodeCache.save(nodeVehicle);
|
||||
//获取缓存内节点的公网/内网信息
|
||||
NodeInfo nodeInfo = nodeCache.get(loadNodeId);
|
||||
//获取缓存内节点的公网/内网信息 返回公网IP
|
||||
// 返回公网IP
|
||||
return nodeInfo.getPublicIdAddress();
|
||||
}
|
||||
|
||||
|
@ -94,6 +100,8 @@ public class GatewayLoadServiceImpl implements GatewayLoadService {
|
|||
// 尝试获取锁,最多等待10秒,持有锁60秒后自动释放
|
||||
// if (refreshLoadLock.tryLock(10, 60, TimeUnit.SECONDS)) {
|
||||
// 在锁内执行刷新负载的逻辑
|
||||
|
||||
//获取 所有手机节点ID和对应的连接数
|
||||
List<WorkGatewayNode> workGatewayNodes = nodeScoreCache.getNodeScore();
|
||||
|
||||
//车辆上线总数量
|
||||
|
@ -105,14 +113,19 @@ public class GatewayLoadServiceImpl implements GatewayLoadService {
|
|||
//空余连接数
|
||||
long vehicleOnlineNum = vehicleMaxOnlineNUm - veicleOnlineNowNum;
|
||||
|
||||
//转换
|
||||
//计算权重
|
||||
List<WorkGatewayNode> workGatewayNodeWeight = workGatewayNodes.stream()
|
||||
.map(workGatewayNode -> WorkGatewayNode.builder()
|
||||
.nodeId(workGatewayNode.getNodeId())
|
||||
.weight(Integer.parseInt(String.valueOf(vehicleOnlineNum / (80L - workGatewayNode.getWeight()))))
|
||||
.weight((int) (((double) LoadConstants.MAXIMUM - workGatewayNode.getWeight()) / vehicleOnlineNum * LoadConstants.BE_COMMON))
|
||||
.build())
|
||||
.toList();
|
||||
|
||||
|
||||
System.out.println(workGatewayNodes);
|
||||
|
||||
System.out.println(workGatewayNodeWeight);
|
||||
|
||||
List<String> loadNodeList = new ArrayList<>();
|
||||
|
||||
int count = workGatewayNodeWeight.stream().mapToInt(WorkGatewayNode::getWeight).sum();
|
||||
|
@ -163,32 +176,33 @@ public class GatewayLoadServiceImpl implements GatewayLoadService {
|
|||
/**
|
||||
* 动态ECS
|
||||
*/
|
||||
public void dynamicECS(){
|
||||
|
||||
//车辆上线总数量
|
||||
long vehicleMaxOnlineNUm = getNodeMaxOnlineNum();
|
||||
|
||||
//目前连接数
|
||||
Long nodeNowNum = nodeScoreCache.getNodeNowNum();
|
||||
|
||||
//负载率
|
||||
BigDecimal loadRate = new BigDecimal(vehicleMaxOnlineNUm).divide(new BigDecimal(nodeNowNum), 0, BigDecimal.ROUND_HALF_UP);
|
||||
|
||||
if (loadRate.longValue() > 80){
|
||||
//扩容
|
||||
}else if (loadRate.longValue() <20 ){
|
||||
//缩容
|
||||
}
|
||||
}
|
||||
// public void dynamicLoad() {
|
||||
//
|
||||
// //车辆上线总数量
|
||||
// long vehicleMaxOnlineNUm = getNodeMaxOnlineNum();
|
||||
//
|
||||
// //目前连接数
|
||||
// Long nodeNowNum = nodeScoreCache.getNodeNowNum();
|
||||
//
|
||||
// //负载率
|
||||
// BigDecimal loadRate = new BigDecimal(vehicleMaxOnlineNUm).divide(new BigDecimal(nodeNowNum), 0, BigDecimal.ROUND_HALF_UP);
|
||||
//
|
||||
// if (loadRate.longValue() > 80) {
|
||||
// //扩容
|
||||
// } else if (loadRate.longValue() < 20) {
|
||||
// //缩容
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* 获取最大连接数
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Long getNodeMaxOnlineNum(){
|
||||
public Long getNodeMaxOnlineNum() {
|
||||
List<WorkGatewayNode> workGatewayNodes = nodeScoreCache.getNodeScore();
|
||||
return workGatewayNodes.size() * 80L;
|
||||
return workGatewayNodes.size() * LoadConstants.MAXIMUM;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,9 @@ package com.muyu.task;
|
|||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.muyu.aly.ALYunEcsService;
|
||||
import com.muyu.aly.model.EcsSelectModel;
|
||||
import com.muyu.aly.model.InstanceInfo;
|
||||
import com.muyu.common.constant.Constans;
|
||||
import com.muyu.common.model.TotalNumber;
|
||||
import com.muyu.gateway.cache.*;
|
||||
import com.muyu.gateway.model.NodeInfo;
|
||||
|
@ -19,6 +21,7 @@ import org.springframework.scheduling.annotation.Scheduled;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -31,6 +34,17 @@ import java.util.List;
|
|||
@AllArgsConstructor
|
||||
public class Collection {
|
||||
|
||||
/**
|
||||
* 最少节点数量
|
||||
*/
|
||||
private final static Integer mainNumber = 1;
|
||||
|
||||
/**
|
||||
* 判断连接阈值
|
||||
*/
|
||||
private final static Integer maxNumber = 21;
|
||||
private final static Integer beforemaxNumber = 20;
|
||||
|
||||
/**
|
||||
* 网关负载节点缓存
|
||||
*/
|
||||
|
@ -72,9 +86,13 @@ public class Collection {
|
|||
@Autowired
|
||||
private ContractionVolume contractionVolume;
|
||||
|
||||
/**
|
||||
* 阿里云方法
|
||||
*/
|
||||
@Autowired
|
||||
private ALYunEcsService alYunEcsService;
|
||||
|
||||
|
||||
/**
|
||||
* 定时扫描节点信息
|
||||
*/
|
||||
|
@ -82,21 +100,24 @@ public class Collection {
|
|||
public void scheduledEcsCompanding() throws Exception {
|
||||
|
||||
//查询阿里云是否存在实例
|
||||
// EcsSelectModel ecsSelectModel = new EcsSelectModel();
|
||||
// List<String> addArryList = new ArrayList<>();
|
||||
// addArryList.add("Myname");
|
||||
// ecsSelectModel.setInstanceNameList(addArryList);
|
||||
EcsSelectModel ecsSelectModel = new EcsSelectModel();
|
||||
List<String> addArryList = new ArrayList<>();
|
||||
addArryList.add("Myname");
|
||||
ecsSelectModel.setInstanceNameList(addArryList);
|
||||
//实例集合
|
||||
List<InstanceInfo> instanceLists = alYunEcsService.selectECS("Myname");
|
||||
List<InstanceInfo> instanceLists = alYunEcsService.selectECS(ecsSelectModel);
|
||||
|
||||
//节点计数
|
||||
Long nodeNumber = 0L;
|
||||
Long nodeNumber = Constans.NUMERICAL_VALUE_LONG_ZERO;
|
||||
|
||||
//所有节点连接数总数
|
||||
long connectionTotal = 0L;
|
||||
long connectionTotal = Constans.NUMERICAL_VALUE_LONG_ZERO;
|
||||
|
||||
//判断实例集合是否为空
|
||||
if (!instanceLists.isEmpty()){
|
||||
//删除连接数缓存
|
||||
nodeScoreCache.delete();
|
||||
|
||||
// 判断实例集合是否为空
|
||||
if (!instanceLists.isEmpty()) {
|
||||
|
||||
//将实例存入缓存
|
||||
for (InstanceInfo instance : instanceLists) {
|
||||
|
@ -113,70 +134,68 @@ public class Collection {
|
|||
// 将新的 NodeInfo 对象放入缓存
|
||||
nodeCache.put(nodeInfo);
|
||||
|
||||
//获取每个FluxMQ运行信息
|
||||
String URL = "http://" + instance.getPublicIpAddress()+":8080/public/cluster";
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
//查询收集节点连接数
|
||||
int connectSize = querymqttConnections(instance.getPublicIpAddress());
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(URL)
|
||||
.get()
|
||||
.addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
|
||||
.addHeader("Accesstoken", "")
|
||||
.build();
|
||||
log.info("当前:" + instance.getInstanceId() + ",的连接数:" + connectSize);
|
||||
|
||||
try {
|
||||
Response response = client.newCall(request).execute();
|
||||
//计数
|
||||
nodeNumber++;
|
||||
connectionTotal += connectSize;
|
||||
|
||||
JSONArray jsonArray = JSONArray.parseArray(response.body().string());
|
||||
JSONObject jsonObject = jsonArray.getJSONObject(0);
|
||||
JSONObject mqttInfo = jsonObject.getJSONObject("mqttInfo");
|
||||
int connectSize = mqttInfo.getIntValue("connectSize");
|
||||
//将连接数存入缓存
|
||||
// key:网关负载业务 value:网关节点ID + 连接数
|
||||
NodeJoin nodeJoin = new NodeJoin();
|
||||
nodeJoin.setNodeId(instance.getInstanceId());
|
||||
nodeJoin.setLinkingNumber(Long.valueOf(connectSize));
|
||||
nodeScoreCache.save(nodeJoin);
|
||||
|
||||
log.info("当前:" + instance.getInstanceId() + ",的连接数:" + connectSize);
|
||||
|
||||
//计数
|
||||
nodeNumber++;
|
||||
connectionTotal+=connectSize;
|
||||
|
||||
//将连接数存入缓存
|
||||
// key:网关负载业务 value:网关节点ID + 连接数
|
||||
NodeJoin nodeJoin = new NodeJoin();
|
||||
nodeJoin.setNodeId(instance.getInstanceId());
|
||||
nodeJoin.setLinkingNumber(Long.valueOf(connectSize));
|
||||
nodeScoreCache.save(nodeJoin);
|
||||
|
||||
//加层判断,把不满足缩容条件的缓存删除 连接数 > 最低阈值
|
||||
if (connectSize > 20 && nodeReduced.isWhether(instance.getInstanceId())){
|
||||
nodeReduced.remove(instance.getInstanceId());
|
||||
}
|
||||
|
||||
//判断是否达到缩容条件 节点数量 > 1 或 连接数 < 21 必须满足节点数量在两个及以上,且连接数低于21
|
||||
if (instanceLists.size() > 1 && connectSize < 21){
|
||||
//调用缩容方法 记录
|
||||
contractionVolume.reduction(instance.getInstanceId());
|
||||
}
|
||||
|
||||
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
//加层判断,把不满足缩容条件的缓存删除 连接数 > 最低阈值
|
||||
if (connectSize > beforemaxNumber && nodeReduced.isWhether(instance.getInstanceId())) {
|
||||
nodeReduced.remove(instance.getInstanceId());
|
||||
}
|
||||
|
||||
//判断是否达到缩容条件 节点数量 > 1 或 连接数 < 21 必须满足节点数量在两个及以上,且连接数低于21
|
||||
if (instanceLists.size() > mainNumber && connectSize < maxNumber) {
|
||||
//调用缩容方法 记录
|
||||
contractionVolume.reduction(instance.getInstanceId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (connectionTotal > 0){
|
||||
//封装节点数量和节点连接总数
|
||||
TotalNumber totalNumber = new TotalNumber();
|
||||
totalNumber.setConnectionTotal(connectionTotal);
|
||||
totalNumber.setNodeNumber(nodeNumber);
|
||||
//调用扩容方法去判断是否需要扩容
|
||||
contractionVolume.contractionVolume(totalNumber);
|
||||
}
|
||||
//封装节点数量和节点连接总数
|
||||
TotalNumber totalNumber = new TotalNumber();
|
||||
totalNumber.setConnectionTotal(connectionTotal);
|
||||
totalNumber.setNodeNumber(nodeNumber);
|
||||
//调用扩容方法去判断是否需要扩容
|
||||
contractionVolume.contractionVolume(totalNumber);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public int querymqttConnections(String publicIPaddress){
|
||||
|
||||
//获取每个FluxMQ运行信息
|
||||
String URL = Constans.HTTP_REQUEST_HEAD
|
||||
+ publicIPaddress
|
||||
+ Constans.HTTP_REQUEST_ADDRESS;
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(URL)
|
||||
.get()
|
||||
.addHeader(Constans.HTTP_REQUEST_ADDHEADER_AGENT, Constans.HTTP_REQUEST_ADDHEADER_APIFOX)
|
||||
.addHeader(Constans.HTTP_REQUEST_ADDHEADER_ACCESSTOKEN, Constans.HTTP_REQUEST_NULL_STRING)
|
||||
.build();
|
||||
|
||||
try {
|
||||
Response response = client.newCall(request).execute();
|
||||
JSONArray jsonArray = JSONArray.parseArray(response.body().string());
|
||||
JSONObject jsonObject = jsonArray.getJSONObject(Constans.NUMERICAL_VALUE_ZERO);
|
||||
JSONObject mqttInfo = jsonObject.getJSONObject(Constans.HTTP_REQUEST_MQTTINFO);
|
||||
return mqttInfo.getIntValue(Constans.HTTP_REQUEST_CONNECTSIZE);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,11 +4,13 @@ import com.muyu.aly.ALYunEcsService;
|
|||
import com.muyu.common.constant.LoadConstants;
|
||||
import com.muyu.common.model.TotalNumber;
|
||||
import com.muyu.gateway.cache.NodeReduced;
|
||||
import com.muyu.gateway.cache.VehicleLineNodeCache;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
|
@ -20,6 +22,16 @@ import java.util.concurrent.TimeUnit;
|
|||
@Component
|
||||
@Log4j2
|
||||
public class ContractionVolume {
|
||||
/**
|
||||
* 网关车辆对应网关节点 key:实例ID value:VIN
|
||||
*/
|
||||
private final VehicleLineNodeCache vehicleLineNodeCache;
|
||||
|
||||
/**
|
||||
* 数值 5
|
||||
*/
|
||||
private final static Integer TimeExpired = 5;
|
||||
|
||||
@Autowired
|
||||
private ALYunEcsService alYunEcsService;
|
||||
|
||||
|
@ -40,13 +52,21 @@ public class ContractionVolume {
|
|||
//查询剩余过期时间 秒
|
||||
Long expire = nodeReduced.remainingTime(nodeId);
|
||||
//获取 5分钟的秒值
|
||||
long fiveMinutesSeconds = TimeUnit.MINUTES.toSeconds(5);
|
||||
long fiveMinutesSeconds = TimeUnit.MINUTES.toSeconds(TimeExpired);
|
||||
//打印
|
||||
log.info("空闲节点 :" + nodeId + "的剩余时间:" + expire + "/秒");
|
||||
|
||||
//比较 剩余时间 小于5分钟
|
||||
if (expire < fiveMinutesSeconds){
|
||||
//数据迁移 释放节点
|
||||
//根据节点ID获取缓存内的车辆VIN值
|
||||
Set<String> vehicleVinSetList = vehicleLineNodeCache.get(nodeId);
|
||||
//判断是否存在车辆信息
|
||||
if (!vehicleVinSetList.isEmpty()){
|
||||
//执行下线
|
||||
}
|
||||
|
||||
|
||||
//删除节点信息
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +87,7 @@ public class ContractionVolume {
|
|||
log.error("当前未存在节点信息");
|
||||
try {
|
||||
//创建实例方法 【2台】
|
||||
// alYunEcsService.createAnServer(LoadConstants.IS_NULL);
|
||||
//alYunEcsService.createAnServer(LoadConstants.IS_NULL);
|
||||
} catch (Exception e) {
|
||||
log.error("扩容失败!!!!!");
|
||||
e.printStackTrace();
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
server:
|
||||
port: 9209
|
||||
|
||||
|
||||
spring:
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
|
||||
aliyun:
|
||||
accessKeyId: LTAI5tPDLpTbAX9bUSrTSrPH
|
||||
accessKeySecret: rbLG6bh8ZSttUPMxUspk9j8XLzvLU0
|
||||
regionId: cn-shanghai
|
||||
image-id: m-uf6hu0jwys1efmiemfxl
|
||||
instance-type: ecs.e-c1m1.large
|
||||
security-group-id: sg-uf6bj6vxp8ruhvffdsau
|
||||
v-switch-id: vsw-uf6sfq669js64lwke0isv
|
||||
internet-max-bandwidth-out: 2
|
||||
internet-charge-type: PayByTraffic
|
||||
size: 20
|
||||
category: cloud_essd
|
||||
instance-charge-type: PostPaid
|
||||
accessKeyId: LTAI5tPDLpTbAX9bUSrTSrPH
|
||||
accessKeySecret: rbLG6bh8ZSttUPMxUspk9j8XLzvLU0
|
||||
regionId: cn-shanghai
|
||||
image-id: m-uf6hu0jwys1efmiemfxl
|
||||
instance-type: ecs.e-c1m1.large
|
||||
security-group-id: sg-uf6bj6vxp8ruhvffdsau
|
||||
v-switch-id: vsw-uf6sfq669js64lwke0isv
|
||||
internet-max-bandwidth-out: 2
|
||||
internet-charge-type: PayByTraffic
|
||||
size: 20
|
||||
category: cloud_essd
|
||||
instance-charge-type: PostPaid
|
||||
endpoint: ecs.aliyuncs.com
|
||||
|
|
Loading…
Reference in New Issue