343 lines
14 KiB
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));
|
|
}
|
|
}
|
|
}
|