zn-car/src/main/java/com/car/config/InitConnectWeight.java

343 lines
14 KiB
Java

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<String, String> 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<ConnectWeight> connectWeightList = new ArrayList<>();
ArrayList<String> 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<List<String>> ipListList = describeInstancesResponse.getBody().instances.getInstance().stream().map(instance -> instance.publicIpAddress.ipAddress).collect(Collectors.toList());
for (List<String> 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<String, Object> request = new HashMap<>();
request.put("username", "fluxmq");
request.put("password", "fluxmq");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Map<String, Object>> r = new HttpEntity<Map<String, Object>>(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<String> 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<String> 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<String, Double> hashMap = new HashMap<>(){{
// for (String s : ipList) {
// put(s,0.8-connectWeightList.get(ipList.indexOf(s)).getWeightValue()/100);
// }
// }
// };
// List<ConnectWeight> 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<String> 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<String, String> consumer = new KafkaConsumer<>(properties);
// 订阅主题
consumer.subscribe(Collections.singletonList(topic));
}
}
}