TrainNet/src/main/java/com/mobai/openApi/SelectInstances.java

204 lines
8.3 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// This file is auto-generated, don't edit it. Thanks.
package com.mobai.openApi;
import com.alibaba.fastjson2.JSON;
import com.aliyun.ecs20140526.models.DescribeInstancesResponse;
import com.aliyun.ecs20140526.models.DescribeInstancesResponseBody;
import com.aliyun.tea.TeaException;
import com.mobai.domain.MqttServerModel;
import com.mobai.domain.Result;
import com.mobai.domain.flux.ApifoxModel;
import com.mobai.service.FluxGetInfoService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.*;
@Log4j2
@Component
public class SelectInstances {
@Autowired
private FluxGetInfoService fluxGetInfoService;
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* 使用AK&SK初始化账号Client
*
* @return Client
* @throws Exception
*/
public static com.aliyun.ecs20140526.Client createClient() throws Exception {
// 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
// 建议使用更安全的 STS 方式更多鉴权访问方式请参见https://help.aliyun.com/document_detail/378657.html。
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
.setAccessKeyId("LTAI5t7vsLXtqTJKve7JipnX")
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
.setAccessKeySecret("AIyMaSTKQtsB1V5sVqlNAGbQzxgXnS");
// Endpoint 请参考 https://api.aliyun.com/product/Ecs
config.endpoint = "ecs.cn-zhangjiakou.aliyuncs.com";
return new com.aliyun.ecs20140526.Client(config);
}
// 通过接口获取数据
public DescribeInstancesResponse getInfo() {
DescribeInstancesResponse describeInstancesResponse = null;
try {
com.aliyun.ecs20140526.Client client = SelectInstances.createClient();
com.aliyun.ecs20140526.models.DescribeInstancesRequest describeInstancesRequest = new com.aliyun.ecs20140526.models.DescribeInstancesRequest()
// .setImageId("m-8vb8qnidv34yj3nbirhc")
.setRegionId("cn-zhangjiakou");
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
describeInstancesResponse = client.describeInstancesWithOptions(describeInstancesRequest, runtime);
} catch (Exception e) {
throw new RuntimeException(e);
}
return describeInstancesResponse;
}
//1分钟
@Scheduled(cron = "0 0/1 * * * ? ")
//10秒
// @Scheduled(cron = "0/10 * * * * ? ")
public void saveIps() throws Exception {
List<String> ips = new ArrayList<>();
DescribeInstancesResponse response = this.getInfo();
try {
DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstances instances = response.getBody().getInstances();
List<DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance> instance =
instances.getInstance();
for (DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance inst : instance) {
List<String> ipAddress = inst
.getPublicIpAddress()
.getIpAddress();
if (ipAddress.isEmpty()) {
continue;
} else {
ipAddress.forEach(ip -> ips.add(ip));
}
}
log.info("当前实例ip为{}", ips);
} catch (TeaException error) {
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
// 错误 message
log.error("错误信息::{}", error.getMessage());
// 诊断地址
log.warn("诊断地址::{}", error.getData().get("Recommend"));
com.aliyun.teautil.Common.assertAsString(error.message);
} catch (Exception _error) {
TeaException error = new TeaException(_error.getMessage(), _error);
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
// 错误 message
log.error("错误信息::{}", error.getMessage());
// 诊断地址
if (error.getData() == null) {
log.error("错误信息::{}", "error.getData()为空");
} else {
log.error("诊断地址::{}", error.getData().get("Recommend"));
}
com.aliyun.teautil.Common.assertAsString(error.message);
}
List<SmallNode> nodes = new ArrayList<>();
for (String ip : ips) {
Result<ApifoxModel> info = fluxGetInfoService.getInfo(ip);
// 获取连接总数
String string = redisTemplate.opsForValue().get("onlineCar-" + ip);
long connectSize = Long.parseLong(string == null ? "0" : string);
log.info("{}::{}", ip, connectSize);
//添加到一个容器
nodes.add(new SmallNode(ip, connectSize));
}
//负载均横方法
this.getArithmetic(nodes);
}
/**
* 负载均衡算法
*
* @param nodes
*/
private void getArithmetic(List<SmallNode> nodes) {
// ip num 数量的容器
Map<String, BigDecimal> arithmet = new HashMap<>();
BigDecimal sum = new BigDecimal(0);
//获取所有的 键
for (SmallNode node : nodes) {
BigDecimal value = BigDecimal.valueOf(80 - node.getNum());
//获取总量
sum = sum.add(value);
arithmet.put(node.getIp(), value);
}// 根据权重总和计算每个节点的特定比例
log.info("总可负载量:{}", arithmet);
List<MqttServerModel> ips = new ArrayList<>();
//获取每个ip的分配率
for (String ip : arithmet.keySet()) {
//概率
BigDecimal probability = arithmet.get(ip).divide(sum, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
arithmet.put(ip, probability);
log.info("{}可负载率(权重值){}", ip, probability);
}
Set<String> ipSet = arithmet.keySet();
BigDecimal finalSum = sum;
Map<String, Integer> map = new HashMap<>();
// 转换成数量
ipSet.forEach(ip -> map.put(ip, arithmet.get(ip).multiply(finalSum).intValue() / 100));
Long i = 0L;
log.info("ip对应可分配车辆{}", map);
int sumInit = map.values().stream().mapToInt(num -> num).sum();
while (true) {
ipSet = map.keySet();
Iterator<String> iterator = ipSet.iterator();
i++;
while (iterator.hasNext()) {
MqttServerModel mqttServerModel = new MqttServerModel();
String ip = iterator.next();
for (SmallNode node : nodes) {
if (node.ip.equals(ip)) mqttServerModel = new MqttServerModel(ip, "topic" + nodes.indexOf(node));
}
ips.add(mqttServerModel);
int i1 = map.get(ip) - 1;
map.put(ip, i1);
if (i1 == 0) {
iterator.remove();
map.remove(ip);
}
}
if (ips.size() == sumInit) {
break;
}
}
redisTemplate.opsForList().leftPush("fluxMq", JSON.toJSONString(ips));
// 可负载IP轮询排列
log.info("排列ip,{}", ips);
Boolean mqttIp = redisTemplate.delete("mqttIp");
ips.forEach(mqtt -> redisTemplate.opsForList().leftPush("mqttIp", JSON.toJSONString(mqtt)));
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class SmallNode {
private String ip;
private long num;
}
}