// This file is auto-generated, don't edit it. Thanks. package com.mobai.openApi; import com.aliyun.ecs20140526.models.DescribeInstancesResponse; import com.aliyun.ecs20140526.models.DescribeInstancesResponseBody; import com.aliyun.tea.TeaException; import com.mobai.domain.ApifoxModel; import com.mobai.domain.Result; import com.mobai.service.FluxGetInfoService; import lombok.AllArgsConstructor; import lombok.Builder; 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 org.springframework.stereotype.Indexed; import reactor.core.publisher.Flux; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.util.stream.Collector; import java.util.stream.Collectors; @Log4j2 @Component public class SelectInstences { @Autowired private FluxGetInfoService fluxGetInfoService; @Autowired private RedisTemplate 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); } @Scheduled(cron = "0/10 * * * * ? ") public void saveIps() throws Exception { List ips = new ArrayList<>(); com.aliyun.ecs20140526.Client client = SelectInstences.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(); try { // 复制代码运行请自行打印 API 的返回值 DescribeInstancesResponse describeInstancesResponse = client.describeInstancesWithOptions(describeInstancesRequest, runtime); DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstances instances = describeInstancesResponse.getBody().getInstances(); List instance = instances.getInstance(); for (DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance inst : instance) { List 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 nodes = new ArrayList<>(); for (String ip : ips) { Result info = fluxGetInfoService.getInfo(ip); //连接总数 long connectSize = info.getData().getMqttInfo().getConnectSize(); log.info("{}::{}",ip,connectSize); //添加到一个容器 nodes.add(new SmallNode(ip,connectSize)); } //负载均横方法 this.getArithmetic(nodes); } /** * 负载均衡算法 * * @param nodes */ private void getArithmetic(List nodes) { // ip num 数量的容器 Map 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); }// 根据权重总和计算每个节点的特定比例 System.out.println (arithmet ); log.info("总可负载量:{}",arithmet); List 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 ipSet = arithmet.keySet(); BigDecimal finalSum = sum; Map map = new HashMap<>(); // 转换成数量 ipSet.forEach(ip -> map.put(ip,arithmet.get(ip).multiply(finalSum).intValue()/100) ); Long i = 0L; System.out.println(map); while (true){ ipSet = map.keySet(); Iterator iterator = ipSet.iterator(); i++; while (iterator.hasNext()){ i++; String ip = iterator.next(); ips.add(ip); int i1 = map.get(ip) - 1; map.put(ip,i1); if (map.get(ip).equals(0)){ map.remove(ip); } } if (i.equals(finalSum)){ break; } System.out.println(i); } // 可负载IP轮询排列 System.out.println(arithmet); System.out.println(ips); } @Data @AllArgsConstructor @NoArgsConstructor class SmallNode{ private String ip; private long num; } }