package com.car.config; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.aliyun.ecs20140526.Client; import com.aliyun.ecs20140526.models.DescribeInstancesRequest; import com.aliyun.ecs20140526.models.DescribeInstancesResponse; import com.aliyun.tea.TeaException; import com.aliyun.teautil.models.RuntimeOptions; import com.car.demos.ConnectWeight; import com.car.demos.car.LoadEnterNumber; import com.car.demos.car.Node; import com.car.service.impl.ConnectServiceImpl; import lombok.extern.slf4j.Slf4j; import org.apache.kafka.clients.admin.AdminClient; import org.apache.kafka.clients.admin.CreateTopicsResult; import org.apache.kafka.clients.admin.ListTopicsResult; import org.apache.kafka.clients.admin.NewTopic; import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.consumer.KafkaConsumer; import org.apache.kafka.common.serialization.StringDeserializer; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.*; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; /** * 初始化连接权重 InitConnectWeight * * @author Yangle * Date 2024/5/28 21:41 */ @Component @Slf4j public class InitConnectWeight implements ApplicationRunner { @Autowired private RedisTemplate redisTemplate; @Autowired private RestTemplate restTemplate; @Autowired private ConnectServiceImpl connectService; @Autowired private RabbitTemplate rabbitTemplate; @Override public void run(ApplicationArguments args) throws ExecutionException, InterruptedException { connectService.loadCenterDel(); connectService.delNode(); List connectWeightList = new ArrayList<>(); ArrayList ipList = new ArrayList<>(); LoadEnterNumber loadEnterNumber = new LoadEnterNumber(); Client client = null; //获取阿里云客户端 try { client = ConnectServiceImpl.createClient(); } catch (Exception e) { throw new RuntimeException(e); } //获取所有实例 DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest() .setRegionId("cn-shanghai") .setStatus("Running"); RuntimeOptions runtime = new RuntimeOptions(); try { // 复制代码运行请自行打印 API 的返回值 DescribeInstancesResponse describeInstancesResponse = client.describeInstancesWithOptions(describeInstancesRequest, runtime); // 获取实例ip List> ipListList = describeInstancesResponse.getBody().instances.getInstance().stream().map(instance -> instance.publicIpAddress.ipAddress).collect(Collectors.toList()); for (List strings : ipListList) { for (String ip : strings) { if (!ip.equals("47.103.75.98")){ ipList.add(ip); } } System.out.println("------------------------"); } } catch (TeaException error) { // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。 // 错误 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); // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。 // 错误 message System.out.println(error.getMessage()); // 诊断地址 System.out.println(error.getData().get("Recommend")); com.aliyun.teautil.Common.assertAsString(error.message); } log.info("ipList:{}", ipList); rabbitTemplate.convertAndSend("ip",ipList); //网关收集节点 int gatewayNum = ipList.size(); //数据解析结点数量 int dataNum=0; //整体负载率 double overallLoad=0; //总车辆 int connectEventSize =0; //内存使用率 Double memoryUseRate = null; //cpu使用率 Double cpuUsage = null; //权重使用率 Double nodeWeights =null; //遍历所有ip,获取每一个服务的连接数 for (String ip : ipList) { //网关收集节点 log.info("gatewayNum:{}", gatewayNum); //fluxMq连接 String url = "http://" + ip + ":8080/public/login"; Map request = new HashMap<>(); request.put("username", "fluxmq"); request.put("password", "fluxmq"); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON); HttpEntity> r = new HttpEntity>(request, httpHeaders); String result = restTemplate.postForObject(url, r, String.class); //整体负载率 int total = 0; //http://fluxmq.muyu.icu/public/cluster //获取FluxMq运行时详情信息 int nextInt = new Random().nextInt(1000); String getInfoUrl = "http://" + ip + ":8080/public/cluster?random=" + nextInt; HttpHeaders httpHeadersGetInfo = new HttpHeaders(); httpHeadersGetInfo.setContentType(MediaType.APPLICATION_JSON); httpHeadersGetInfo.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); httpHeadersGetInfo.set("Cookie", result); HttpEntity getInfoRequest = new HttpEntity(httpHeadersGetInfo); ResponseEntity responseInfo = restTemplate.exchange(getInfoUrl, HttpMethod.GET, getInfoRequest, String.class, 1); log.info("响应是:{}", responseInfo.getBody()); JSONArray jsonArray = JSON.parseArray(responseInfo.getBody()); System.out.println("json"+jsonArray); if (jsonArray.size() > 0) { JSONObject jsonObject = jsonArray.getJSONObject(0); // Integer connectSize = jsonObject.getJSONObject("mqttInfo").getJSONObject("runtimes").getInteger("mqtt.connect"); //获取节点名称 String nodeName = jsonObject.getString("nodeName"); //获取内存使用率 JSONObject flowInfo = jsonObject.getJSONObject("jvmInfo"); //内存大小 String heapMaxSize = flowInfo.getString("heap-max"); //堆内存使用率 String heapUsedSize = flowInfo.getString("heap-used"); // 定义单位到字节的转换系数 final double GB_TO_BYTES = 1024 * 1024 * 1024; // 1 GB = 1024^3 bytes final double MB_TO_BYTES = 1024 * 1024; // 1 MB = 1024^2 bytes // 解析字符串并转换为字节 double maxHeapBytes = Double.parseDouble(heapMaxSize.substring(0, heapMaxSize.length() - 3)) * GB_TO_BYTES; // 去掉"GB"并转换 double usedHeapBytes = Double.parseDouble(heapUsedSize.substring(0, heapUsedSize.length() - 3)) * MB_TO_BYTES; // 去掉"MB"并转换 // 计算使用率(百分比) BigDecimal divide = BigDecimal.valueOf((usedHeapBytes / maxHeapBytes) * 100).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP); //内存率 memoryUseRate=divide.doubleValue(); //cpu JSONObject cpuInfo = jsonObject.getJSONObject("cpuInfo"); String string = cpuInfo.getString("user"); cpuUsage = Double.valueOf(string.split("%")[0]); //获取mqtt JSONObject mqttInfo = jsonObject.getJSONObject("mqttInfo"); //连接数 Integer connectSize = Integer.valueOf(mqttInfo.getString("connectSize")); //小车总连接数 connectEventSize = Integer.valueOf(mqttInfo.getString("connectEventSize")); connectWeightList.add(new ConnectWeight(ip,100-connectSize)); //权重值 Integer weightValue = 100 - connectSize; nodeWeights = Double.valueOf(weightValue/100); Node build = Node.builder() .nodeName(ip) .memoryUseRate(memoryUseRate) .cpuUsage(cpuUsage) .nodeWeights(nodeWeights) .build(); connectService.nodeAdd(build); log.info("链接数量:{}", connectSize); } else { log.info("得到的相应数据为null"); } } log.info("车辆在线是",connectEventSize); //每个连接数的权重总和 Integer sum =0; for (ConnectWeight connectWeight : connectWeightList) { sum = (int) (sum+connectWeight.getWeightValue()); } System.out.println("sum"+sum); int max=0; //权重总和 double sumOfWeights=0; for (ConnectWeight connectWeight : connectWeightList) { BigDecimal divide = BigDecimal.valueOf(connectWeight.getWeightValue() * 100).divide(BigDecimal.valueOf(sum), 0, RoundingMode.DOWN); int result = divide.intValue(); if (result > max){ max = result; } connectWeight.setWeightValue(result); System.out.println("100次轮询次数:{}"+result); sumOfWeights+=connectWeight.getWeightValue(); } overallLoad =sumOfWeights/ipList.size(); log.info("总负载",overallLoad); LoadEnterNumber build = LoadEnterNumber.builder() .carSum(connectEventSize) .gatewayNum(ipList.size()) .dataNum(dataNum) .overallLoad(overallLoad) .build(); connectService.LoadCenterAdd(build); ArrayList weightIpList = new ArrayList<>(); redisTemplate.delete("subscript"); for (int i = 0; i <= max; i++) { for (ConnectWeight connectWeight : connectWeightList) { // log.info("权重值:{}",connectWeight.getWeightValue()); if (connectWeight.getWeightValue() > i) { weightIpList.add(connectWeight.getCarServerIp()); }else if (connectWeight.getWeightValue() == max ){ weightIpList.add(connectWeight.getCarServerIp()); // log.info("轮询结果:{}",connectWeight.getCarServerIp()); } } } createTopic(); // 存入redis redisTemplate.delete("ips"); for (String ip : weightIpList) { redisTemplate.opsForList().rightPush("ips",ip); } redisTemplate.opsForValue().set("subscript","0"); // //每台服务器百分之八十 // HashMap hashMap = new HashMap<>(){{ // for (String s : ipList) { // put(s,0.8-connectWeightList.get(ipList.indexOf(s)).getWeightValue()/100); // } // } // }; // List list = hashMap.entrySet().stream() // .map(entry -> new ConnectWeight()) // .collect(Collectors.toList()); } public void createTopic() throws ExecutionException, InterruptedException { Properties properties = System.getProperties(); properties.put("bootstrap.servers", "localhost:9092"); // 替换为您的Kafka集群地址 // 创建AdminClient实例 AdminClient adminClient = AdminClient.create(properties); // 定义要创建的主题名称和分区数 ArrayList topics = new ArrayList<>(); topics.add("test1"); topics.add("test2"); int numPartitions = 8; // 检查主题是否存在并创建新主题 for (String topic : topics) { ListTopicsResult listTopicsResult = adminClient.listTopics(); if (!listTopicsResult.names().get().contains(topic)) { // 主题不存在,创建新主题 NewTopic newTopic = new NewTopic(topic, numPartitions, (short) 1); CreateTopicsResult createTopicsResult = adminClient.createTopics(Collections.singletonList(newTopic)); // 等待主题创建完成 try { createTopicsResult.all().get(); System.out.println("主题创建成功:" + topic); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); System.err.println("主题创建失败:" + topic); } } else { // 主题已存在,可以选择跳过或更新配置 System.out.println("主题已存在:" + topic); } createConsumers(topic); } } public void createConsumers(String topic) { // 定义消费者组ID String groupId = topic; // 配置消费者属性 Properties properties = System.getProperties(); properties.put("bootstrap.servers", "localhost:9092"); // 替换为您的Kafka集群地址 properties.put("key.deserializer", StringDeserializer.class.getName()); properties.put("value.deserializer", StringDeserializer.class.getName()); properties.put(ConsumerConfig.GROUP_ID_CONFIG, groupId); // 创建8个消费者实例 for (int i = 0; i < 8; i++) { KafkaConsumer consumer = new KafkaConsumer<>(properties); // 订阅主题 consumer.subscribe(Collections.singletonList(topic)); } } }