feat:负载中心
commit
77ade6288e
|
@ -0,0 +1,38 @@
|
|||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
|
@ -0,0 +1,8 @@
|
|||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" defaultCharsetForPropertiesFiles="UTF-8">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
<file url="PROJECT" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,5 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
</profile>
|
||||
</component>
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,171 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.load</groupId>
|
||||
<artifactId>Load_center</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<!-- 规定SpringBoot版本 -->
|
||||
<parent>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<version>2.6.2</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.paho</groupId>
|
||||
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||
<version>1.2.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- redis-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.lettuce</groupId>
|
||||
<artifactId>lettuce-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.redisson</groupId>
|
||||
<artifactId>redisson</artifactId>
|
||||
<version>3.16.0</version>
|
||||
</dependency>
|
||||
<!-- http协议 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<version>4.4.12</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.13</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.12.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- web -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<!-- 测试 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Druid -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>1.2.8</version>
|
||||
</dependency>
|
||||
|
||||
<!-- servlet 依赖. -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>8.0.11</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<!-- Mybatis 依赖配置 -->
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>2.2.2</version>
|
||||
</dependency>
|
||||
<!-- PageHelper mybatis分页插件 -->
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||
<version>1.4.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- lombok小辣椒依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
<!-- json-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.79</version>
|
||||
</dependency>
|
||||
|
||||
<!-- quartz定时任务-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-quartz</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
<!-- mq-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>ecs20140526</artifactId>
|
||||
<version>5.1.8</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,19 @@
|
|||
package com.load;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* 启动类
|
||||
*
|
||||
* @author YunFei·Du
|
||||
* @ClassName: LoadApplication
|
||||
* @Description: 启动类
|
||||
* @CreateTime: 2024/5/27 09:50
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class LoadApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(LoadApplication.class,args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.load;
|
||||
|
||||
/**
|
||||
* @ClassName MqttApplication
|
||||
* @Description 描述
|
||||
* @Author YunFei.Du
|
||||
* @Date 2024/5/30 9:19
|
||||
*/
|
||||
public class MqttApplication {
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package com.load;
|
||||
|
||||
import org.eclipse.paho.client.mqttv3.*;
|
||||
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
||||
|
||||
/**
|
||||
* 订阅 MQTT 主题
|
||||
*/
|
||||
public class SubscribeSample {
|
||||
public static void main(String[] args) {
|
||||
/**
|
||||
* 代理地址
|
||||
*/
|
||||
String broker = "tcp://39.100.87.192:1883";
|
||||
/**
|
||||
* 主题
|
||||
*/
|
||||
String topic = "mqtt/test";
|
||||
String username = "emqx";
|
||||
String password = "public";
|
||||
/**
|
||||
* 客户端ID(随机)
|
||||
*/
|
||||
String clientid = "subscribe_client";
|
||||
int qos = 0;
|
||||
|
||||
try {
|
||||
MqttClient client = new MqttClient(broker, clientid, new MemoryPersistence());
|
||||
// 连接参数
|
||||
MqttConnectOptions options = new MqttConnectOptions();
|
||||
options.setUserName(username);
|
||||
options.setPassword(password.toCharArray());
|
||||
options.setConnectionTimeout(60);
|
||||
// 堵塞60S
|
||||
options.setKeepAliveInterval(60);
|
||||
// 设置回调
|
||||
client.setCallback(new MqttCallback() {
|
||||
|
||||
public void connectionLost(Throwable cause) {
|
||||
System.out.println("connectionLost: " + cause.getMessage());
|
||||
}
|
||||
|
||||
public void messageArrived(String topic, MqttMessage message) {
|
||||
System.out.println("topic: " + topic);
|
||||
System.out.println("Qos: " + message.getQos());
|
||||
System.out.println("message content: " + new String(message.getPayload()));
|
||||
|
||||
}
|
||||
|
||||
public void deliveryComplete(IMqttDeliveryToken token) {
|
||||
System.out.println("deliveryComplete---------" + token.isComplete());
|
||||
}
|
||||
|
||||
});
|
||||
client.connect(options);
|
||||
client.subscribe(topic, qos);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
package com.load.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.load.domain.ConnectWeight;
|
||||
import com.load.util.ECSTool;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 初始化连接权重
|
||||
*
|
||||
* @author YunFei·Du
|
||||
* @ClassName: InitConnectWeight
|
||||
* @Description: 初始化连接权重
|
||||
* @CreateTime: 2024/5/27 21:31
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class InitConnectWeight implements ApplicationRunner {
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
|
||||
ArrayList<ConnectWeight> connectWeightList = new ArrayList<>();
|
||||
|
||||
ArrayList<String> ipList = new ArrayList<>();
|
||||
|
||||
Client client = null;
|
||||
//获取阿里云客户端
|
||||
try {
|
||||
client = ECSTool.createClient();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
//获取所有实例
|
||||
DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest()
|
||||
.setRegionId("cn-zhangjiakou");
|
||||
// .setInstanceType("ecs.e-c1m2.xlarge");
|
||||
RuntimeOptions runtime = new RuntimeOptions();
|
||||
try {
|
||||
// 复制代码运行请自行打印 API 的返回值
|
||||
DescribeInstancesResponse describeInstancesResponse = client.describeInstancesWithOptions(describeInstancesRequest, runtime);
|
||||
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) {
|
||||
ipList.add(ip);
|
||||
}
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
||||
//http://fluxmq.muyu.icu/public/login
|
||||
|
||||
//遍历所有ip,获取每一个服务的连接数
|
||||
for (String ip : ipList) {
|
||||
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);
|
||||
|
||||
|
||||
//http://fluxmq.muyu.icu/public/cluster
|
||||
|
||||
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.error("响应是:{}", responseInfo.getBody());
|
||||
|
||||
JSONArray jsonArray = JSON.parseArray(responseInfo.getBody());
|
||||
if (jsonArray.size() > 0) {
|
||||
JSONObject jsonObject = jsonArray.getJSONObject(0);
|
||||
Integer connectSize = Integer.valueOf(jsonObject.getJSONObject("mqttInfo").getString("connectSize"));
|
||||
connectWeightList.add(new ConnectWeight(ip,100-connectSize));
|
||||
log.error("链接数量:{}", connectSize);
|
||||
} else {
|
||||
log.error("得到的相应数据为null");
|
||||
}
|
||||
}
|
||||
// 初始化权重求和变量
|
||||
Integer sum =0;
|
||||
// 遍历ConnectWeight列表,计算所有权重值的总和
|
||||
for (ConnectWeight connectWeight : connectWeightList) {
|
||||
sum = sum + connectWeight.getWeightValue();
|
||||
}
|
||||
|
||||
// 初始化最大轮询次数为0
|
||||
int max = 0;
|
||||
for (ConnectWeight connectWeight : connectWeightList) {
|
||||
log.error("权重值:{}",connectWeight.getWeightValue());
|
||||
// 将权重值转换为百分比并向下取整,得到每一轮的轮询次数
|
||||
Integer result = BigDecimal.valueOf(connectWeight.getWeightValue() * 100).divide(BigDecimal.valueOf(sum), 0, RoundingMode.DOWN).intValue();
|
||||
// 如果计算出的轮询次数大于当前最大值,更新最大值
|
||||
if (result > max){
|
||||
max = result;
|
||||
}
|
||||
// 更新ConnectWeight对象的权重值为计算出的轮询次数
|
||||
connectWeight.setWeightValue(result);
|
||||
// 输出100次轮询次数
|
||||
log.error("100次轮询次数:{}",result);
|
||||
}
|
||||
|
||||
ArrayList<String> weightIpList = new ArrayList<>();
|
||||
|
||||
//轮询出现次数
|
||||
for (int i = 0; i <= max; i++) {
|
||||
for (ConnectWeight connectWeight : connectWeightList) {
|
||||
if (connectWeight.getWeightValue() > i){
|
||||
weightIpList.add(connectWeight.getCarServerIp());
|
||||
}else if (connectWeight.getWeightValue() == max){
|
||||
weightIpList.add(connectWeight.getCarServerIp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//存入redis
|
||||
redisTemplate.delete("ipList");
|
||||
for (String ip : weightIpList) {
|
||||
redisTemplate.opsForList().rightPush("ipList",ip);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package com.load.config;
|
||||
|
||||
import org.springframework.amqp.core.*;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* rabbitMq配置类
|
||||
*
|
||||
* @author YunFei·Du
|
||||
* @ClassName: RabbitmqConfig
|
||||
* @Description: rabbitMq配置类
|
||||
* @CreateTime: 2024/5/27 16:56
|
||||
*/
|
||||
@Configuration
|
||||
public class RabbitmqConfig {
|
||||
public static final String QUEUE_INFORM_EMAIL = "queue_inform_email";
|
||||
public static final String QUEUE_INFORM_SMS = "disconnect_connect";
|
||||
public static final String EXCHANGE_TOPICS_INFORM="exchange_topics_inform";
|
||||
public static final String ROUTINGKEY_EMAIL="inform.#.email.#";
|
||||
public static final String ROUTINGKEY_SMS="inform.#.sms.#";
|
||||
|
||||
|
||||
@Bean(EXCHANGE_TOPICS_INFORM)
|
||||
public Exchange EXCHANGE_TOPICS_INFORM(){
|
||||
//durable(true) 持久化,mq重启之后交换机还在
|
||||
return ExchangeBuilder.topicExchange(EXCHANGE_TOPICS_INFORM).durable(true).build();
|
||||
}
|
||||
|
||||
//声明QUEUE_INFORM_EMAIL队列
|
||||
@Bean(QUEUE_INFORM_EMAIL)
|
||||
public Queue QUEUE_INFORM_EMAIL(){
|
||||
return new Queue(QUEUE_INFORM_EMAIL);
|
||||
}
|
||||
//声明QUEUE_INFORM_SMS队列
|
||||
@Bean(QUEUE_INFORM_SMS)
|
||||
public Queue QUEUE_INFORM_SMS(){
|
||||
return new Queue(QUEUE_INFORM_SMS);
|
||||
}
|
||||
|
||||
//ROUTINGKEY_EMAIL队列绑定交换机,指定routingKey
|
||||
@Bean
|
||||
public Binding BINDING_QUEUE_INFORM_EMAIL(@Qualifier(QUEUE_INFORM_EMAIL) Queue queue,
|
||||
@Qualifier(EXCHANGE_TOPICS_INFORM) Exchange exchange){
|
||||
return BindingBuilder.bind(queue).to(exchange).with(ROUTINGKEY_EMAIL).noargs();
|
||||
}
|
||||
//ROUTINGKEY_SMS队列绑定交换机,指定routingKey
|
||||
@Bean
|
||||
public Binding BINDING_ROUTINGKEY_SMS(@Qualifier(QUEUE_INFORM_SMS) Queue queue,
|
||||
@Qualifier(EXCHANGE_TOPICS_INFORM) Exchange exchange){
|
||||
return BindingBuilder.bind(queue).to(exchange).with(ROUTINGKEY_SMS).noargs();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.load.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* redsi配置类
|
||||
*
|
||||
* @author YunFei·Du
|
||||
* @ClassName: RedisConfoig
|
||||
* @Description: redsi配置类
|
||||
* @CreateTime: 2024/5/27 14:16
|
||||
*/
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
@Bean
|
||||
public RedisTemplate<String,String> redisTemplate(RedisConnectionFactory redisConnectionFactory){
|
||||
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(redisConnectionFactory);
|
||||
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
|
||||
|
||||
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
|
||||
return redisTemplate;
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.load.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* rest配置类
|
||||
*
|
||||
* @author YunFei·Du
|
||||
* @ClassName: RestTemplateConfig
|
||||
* @Description: rest配置类
|
||||
* @CreateTime: 2024/5/27 10:01
|
||||
*/
|
||||
@Configuration
|
||||
public class RestTemplateConfig {
|
||||
@Bean
|
||||
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
|
||||
return new RestTemplate(factory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
|
||||
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
||||
//超时设置
|
||||
factory.setReadTimeout(5000);//ms
|
||||
factory.setConnectTimeout(15000);//ms
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package com.load.consumer;
|
||||
|
||||
import com.load.config.InitConnectWeight;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.DefaultApplicationArguments;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
/**
|
||||
* 断开连接消费者
|
||||
*
|
||||
* @author YunFei·Du
|
||||
* @ClassName: ReceiveHandler
|
||||
* @Description: 断开连接消费者
|
||||
* @CreateTime: 2024/5/27 17:00
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ReceiveHandler {
|
||||
@Autowired
|
||||
private RedisTemplate redisTemplate;
|
||||
@Autowired
|
||||
private InitConnectWeight initConnectWeight;
|
||||
|
||||
//监听sms队列 ADD_LOG_AAA
|
||||
@RabbitListener(queues = {"ADD_LOG_AAA"})
|
||||
public void receiveSms(Message message) {
|
||||
try {
|
||||
initConnectWeight.run(new DefaultApplicationArguments());
|
||||
redisTemplate.delete("count");
|
||||
log.warn("ip权重重新分配成功!");
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
System.out.println("消费者得到的消息: " + new String(message.getBody()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.load.controller;
|
||||
|
||||
import com.load.domain.MqttServerModel;
|
||||
import com.load.domain.Result;
|
||||
import com.load.domain.req.VehicleConnectionReq;
|
||||
import com.load.service.LoadBalanceService;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
/**
|
||||
* 车辆连接
|
||||
*
|
||||
* @author YunFei·Du
|
||||
* @ClassName: ConnectController
|
||||
* @Description: 车辆连接
|
||||
* @CreateTime: 2024/5/27 09:00
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("loadBalance")
|
||||
@Log4j2
|
||||
public class LoadBalanceController {
|
||||
|
||||
|
||||
@Autowired
|
||||
private LoadBalanceService loadBalanceService;
|
||||
|
||||
|
||||
/**
|
||||
* 获取连接
|
||||
*/
|
||||
@PostMapping("/getConnect")
|
||||
public Result<MqttServerModel> getConnect(@RequestBody VehicleConnectionReq vehicleConnectionReq){
|
||||
return loadBalanceService.getConnect(vehicleConnectionReq);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建实例
|
||||
*/
|
||||
@GetMapping("/createConnect")
|
||||
public void createConnect() {
|
||||
loadBalanceService.createConnect ( );
|
||||
log.info ( "创建实例成功" );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.load.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 内存使用情况
|
||||
*
|
||||
* @author YunFei·Du
|
||||
* @ClassName: MemoryUserInfo
|
||||
* @Description: 内存使用情况
|
||||
* @CreateTime: 2024/5/27 15:53
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ConnectUseInfo {
|
||||
|
||||
/**
|
||||
* 节点ID
|
||||
*/
|
||||
private String clusterId;
|
||||
/**
|
||||
* 所属IP
|
||||
*/
|
||||
private String ipAddress;
|
||||
/**
|
||||
* 剩余可连接数量
|
||||
*/
|
||||
private Integer remainingNum;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.load.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 连接权重
|
||||
*
|
||||
* @author YunFei·Du
|
||||
* @ClassName: CarServer
|
||||
* @Description: 车子服务器
|
||||
* @CreateTime: 2024/5/27 09:04
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ConnectWeight {
|
||||
|
||||
/**
|
||||
* 服务器ip
|
||||
*/
|
||||
private String carServerIp;
|
||||
/**
|
||||
* 权重值
|
||||
*/
|
||||
private Integer weightValue;
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package com.load.domain;
|
||||
|
||||
/**
|
||||
* 返回状态码
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class HttpStatus {
|
||||
/**
|
||||
* 操作成功
|
||||
*/
|
||||
public static final int SUCCESS = 200;
|
||||
|
||||
/**
|
||||
* 对象创建成功
|
||||
*/
|
||||
public static final int CREATED = 201;
|
||||
|
||||
/**
|
||||
* 请求已经被接受
|
||||
*/
|
||||
public static final int ACCEPTED = 202;
|
||||
|
||||
/**
|
||||
* 操作已经执行成功,但是没有返回数据
|
||||
*/
|
||||
public static final int NO_CONTENT = 204;
|
||||
|
||||
/**
|
||||
* 资源已被移除
|
||||
*/
|
||||
public static final int MOVED_PERM = 301;
|
||||
|
||||
/**
|
||||
* 重定向
|
||||
*/
|
||||
public static final int SEE_OTHER = 303;
|
||||
|
||||
/**
|
||||
* 资源没有被修改
|
||||
*/
|
||||
public static final int NOT_MODIFIED = 304;
|
||||
|
||||
/**
|
||||
* 参数列表错误(缺少,格式不匹配)
|
||||
*/
|
||||
public static final int BAD_REQUEST = 400;
|
||||
|
||||
/**
|
||||
* 未授权
|
||||
*/
|
||||
public static final int UNAUTHORIZED = 401;
|
||||
|
||||
/**
|
||||
* 访问受限,授权过期
|
||||
*/
|
||||
public static final int FORBIDDEN = 403;
|
||||
|
||||
/**
|
||||
* 资源,服务未找到
|
||||
*/
|
||||
public static final int NOT_FOUND = 404;
|
||||
|
||||
/**
|
||||
* 不允许的http方法
|
||||
*/
|
||||
public static final int BAD_METHOD = 405;
|
||||
|
||||
/**
|
||||
* 资源冲突,或者资源被锁
|
||||
*/
|
||||
public static final int CONFLICT = 409;
|
||||
|
||||
/**
|
||||
* 不支持的数据,媒体类型
|
||||
*/
|
||||
public static final int UNSUPPORTED_TYPE = 415;
|
||||
|
||||
/**
|
||||
* 系统内部错误
|
||||
*/
|
||||
public static final int ERROR = 500;
|
||||
|
||||
/**
|
||||
* 接口未实现
|
||||
*/
|
||||
public static final int NOT_IMPLEMENTED = 501;
|
||||
|
||||
/**
|
||||
* 系统警告消息
|
||||
*/
|
||||
public static final int WARN = 601;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.load.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Mqtt服务器模型
|
||||
* @author YunFei.Du
|
||||
* @date 22:08 2024/5/29
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MqttServerModel {
|
||||
|
||||
/**
|
||||
* MQTT服务节点
|
||||
*/
|
||||
private String broker;
|
||||
|
||||
/**
|
||||
* MQTT订阅主题
|
||||
*/
|
||||
private String topic;
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package com.load.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 响应信息主体
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
public class Result<T> implements Serializable {
|
||||
/**
|
||||
* 成功
|
||||
*/
|
||||
public static final int SUCCESS = HttpStatus.SUCCESS;
|
||||
/**
|
||||
* 失败
|
||||
*/
|
||||
public static final int FAIL = HttpStatus.ERROR;
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 系统警告消息
|
||||
*/
|
||||
private static final int WARN = HttpStatus.WARN;
|
||||
|
||||
private int code;
|
||||
|
||||
private String msg;
|
||||
|
||||
private T data;
|
||||
|
||||
public static <T> Result<T> success () {
|
||||
return restResult(null, SUCCESS, "操作成功");
|
||||
}
|
||||
|
||||
public static <T> Result<T> success (T data) {
|
||||
return restResult(data, SUCCESS, "操作成功");
|
||||
}
|
||||
|
||||
public static <T> Result<T> success (T data, String msg) {
|
||||
return restResult(data, SUCCESS, msg);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error () {
|
||||
return restResult(null, FAIL, "操作失败");
|
||||
}
|
||||
|
||||
public static <T> Result<T> error (String msg) {
|
||||
return restResult(null, FAIL, msg);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error (T data) {
|
||||
return restResult(data, FAIL, "操作失败");
|
||||
}
|
||||
|
||||
public static <T> Result<T> error (T data, String msg) {
|
||||
return restResult(data, FAIL, msg);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error (int code, String msg) {
|
||||
return restResult(null, code, msg);
|
||||
}
|
||||
|
||||
public static <T> Result<T> warn () {
|
||||
return restResult(null, WARN, "操作失败");
|
||||
}
|
||||
|
||||
public static <T> Result<T> warn (String msg) {
|
||||
return restResult(null, WARN, msg);
|
||||
}
|
||||
|
||||
public static <T> Result<T> warn (T data) {
|
||||
return restResult(data, WARN, "操作失败");
|
||||
}
|
||||
|
||||
public static <T> Result<T> warn (T data, String msg) {
|
||||
return restResult(data, WARN, msg);
|
||||
}
|
||||
|
||||
public static <T> Result<T> warn (int code, String msg) {
|
||||
return restResult(null, code, msg);
|
||||
}
|
||||
|
||||
private static <T> Result<T> restResult (T data, int code, String msg) {
|
||||
Result<T> apiResult = new Result<>();
|
||||
apiResult.setCode(code);
|
||||
apiResult.setData(data);
|
||||
apiResult.setMsg(msg);
|
||||
return apiResult;
|
||||
}
|
||||
|
||||
public static <T> Boolean isError (Result<T> ret) {
|
||||
return !isSuccess(ret);
|
||||
}
|
||||
|
||||
public static <T> Boolean isSuccess (Result<T> ret) {
|
||||
return Result.SUCCESS == ret.getCode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.load.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @ClassName VinIp
|
||||
* @Description 描述
|
||||
* @Author YunFei.Du
|
||||
* @Date 2024/5/30 20:34
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class VinIp {
|
||||
String vin;
|
||||
String ip;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.load.domain.req;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author DongZl
|
||||
* @description: 车辆获取连接地址
|
||||
* @Date 2023-11-28 上午 10:32
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class VehicleConnectionReq {
|
||||
|
||||
/**
|
||||
* {
|
||||
* "vehicleVin": "VIN1234567894",
|
||||
* "timestamp": "11111",
|
||||
* "username": "你好",
|
||||
* "nonce": "33"
|
||||
* }
|
||||
*/
|
||||
|
||||
/**
|
||||
* vin
|
||||
*/
|
||||
@JSONField(name = "vehicleVin")
|
||||
private String vehicleVin;
|
||||
|
||||
/**
|
||||
* 时间戳
|
||||
*/
|
||||
private String timestamp;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
@JSONField(name = "username")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 随机字符串
|
||||
*/
|
||||
private String nonce;
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.load.mqtt;
|
||||
|
||||
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
|
||||
import org.eclipse.paho.client.mqttv3.MqttCallback;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 消息回调服务 (回执消息类)
|
||||
* @author YunFei.Du
|
||||
* @date 22:37 2024/5/30
|
||||
*/
|
||||
@Service
|
||||
public class MessageCallbackService implements MqttCallback {
|
||||
|
||||
@Override
|
||||
public void connectionLost(Throwable cause) {
|
||||
System.out.println("connectionLost: " + cause.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageArrived(String topic, MqttMessage message) {
|
||||
System.out.println("topic: " + topic);
|
||||
System.out.println("Qos: " + message.getQos());
|
||||
System.out.println("message content: " + new String(message.getPayload()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliveryComplete(IMqttDeliveryToken token) {
|
||||
System.out.println("deliveryComplete---------" + token.isComplete());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.load.mqtt;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Mqtt工厂
|
||||
* @author YunFei.Du
|
||||
* @date 22:38 2024/5/30
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class MqttFactory {
|
||||
|
||||
private final MessageCallbackService messageCallbackService;
|
||||
// 连接参数
|
||||
|
||||
/**
|
||||
* 创建Mqtt 客户端
|
||||
* @param mqttProperties
|
||||
* @return
|
||||
*/
|
||||
public MqttClient createClient(MqttProperties mqttProperties){
|
||||
MqttClient mqttClient =null;
|
||||
try {
|
||||
mqttClient=new MqttClient ( mqttProperties.getBroker() , mqttProperties.getClientId() , new MemoryPersistence() );
|
||||
} catch (MqttException e) {
|
||||
throw new RuntimeException ( e );
|
||||
}
|
||||
MqttConnectOptions options = new MqttConnectOptions ( );
|
||||
|
||||
if (mqttProperties.isLogin()){
|
||||
options.setUserName ( mqttProperties.getUsername() );
|
||||
options.setPassword ( mqttProperties.getPassword().toCharArray() );
|
||||
}
|
||||
options.setConnectionTimeout(60);
|
||||
options.setKeepAliveInterval(60);
|
||||
mqttClient.setCallback ( messageCallbackService );
|
||||
|
||||
return mqttClient;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.load.mqtt;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* 配置中心
|
||||
* @author YunFei.Du
|
||||
* @date 8:53 2024/5/30
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class MqttProperties {
|
||||
|
||||
private String broker;
|
||||
private String topic;
|
||||
private String username;
|
||||
private String password;
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
* 构建mqtt配置
|
||||
* @param ip
|
||||
* @param topic
|
||||
* @return
|
||||
*/
|
||||
public static MqttProperties configBuild(String ip, String topic){
|
||||
return MqttProperties.builder()
|
||||
.broker("tcp://"+ip+":1883")
|
||||
.topic(topic)
|
||||
.username("admin")
|
||||
.password("public")
|
||||
.clientId("protocol-parsing") //协议解析 定值 --> 配置
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否可以登录
|
||||
* @return
|
||||
*/
|
||||
public boolean isLogin(){
|
||||
// commons-lang3
|
||||
return StringUtils.isBlank ( username ) && !StringUtils.isBlank ( password );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.load.rebbitmq;
|
||||
|
||||
import com.load.mqtt.MqttFactory;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 信息处理器
|
||||
* @author YunFei.Du
|
||||
* @date 9:21 2024/5/30
|
||||
*/
|
||||
@Component
|
||||
@Log4j2
|
||||
public class MsgHandle {
|
||||
|
||||
@Autowired
|
||||
private MqttFactory mqttFactory;
|
||||
// @RabbitListener(queues = {"create.topic"})
|
||||
// private void msg(String msg){
|
||||
// log.info ( "接收到消息:{}" , msg );
|
||||
// MqttProperties mqttProperties = MqttProperties.configBuild ( "39.100.87.192", "mqtt/test" );
|
||||
// mqttFactory.createClient ( mqttProperties );
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.load.rebbitmq;
|
||||
|
||||
import org.springframework.amqp.core.Binding;
|
||||
import org.springframework.amqp.core.BindingBuilder;
|
||||
import org.springframework.amqp.core.DirectExchange;
|
||||
import org.springframework.amqp.core.Queue;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* rabbit 配置类
|
||||
* @author YunFei.Du
|
||||
* @date 8:39 2024/5/31
|
||||
*/
|
||||
@Configuration
|
||||
public class RabbitConfig {
|
||||
@Bean
|
||||
public Queue initQueue() {
|
||||
return new Queue ("create.totic", true);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DirectExchange direct(){
|
||||
return new DirectExchange ("topic.direct");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindingla(DirectExchange direct, Queue initQueue){
|
||||
return BindingBuilder.bind(initQueue)
|
||||
.to(direct)
|
||||
.with("protocol-parsing");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.load.service;
|
||||
/**
|
||||
* 连接服务接口
|
||||
*
|
||||
* @author YunFei·Du
|
||||
* @ClassName: ConnectServer
|
||||
* @Description: 连接服务接口
|
||||
* @CreateTime: 2024/5/27 09:22
|
||||
*/
|
||||
|
||||
import com.load.domain.MqttServerModel;
|
||||
import com.load.domain.Result;
|
||||
import com.load.domain.req.VehicleConnectionReq;
|
||||
|
||||
/**
|
||||
*@ClassName ConnectServer
|
||||
*@Description 描述
|
||||
*@Author YunFei·Du
|
||||
*@Date 2024/5/27 09:22
|
||||
*/
|
||||
public interface LoadBalanceService {
|
||||
Result<MqttServerModel> getConnect(VehicleConnectionReq vehicleConnectionReq);
|
||||
|
||||
void createConnect();
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package com.load.service.impl;
|
||||
|
||||
import com.load.domain.MqttServerModel;
|
||||
import com.load.domain.Result;
|
||||
import com.load.domain.VinIp;
|
||||
import com.load.domain.req.VehicleConnectionReq;
|
||||
import com.load.service.LoadBalanceService;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import static com.load.util.ECSTool.runEcsInstance;
|
||||
|
||||
/**
|
||||
* 服务实现类
|
||||
*
|
||||
* @author YunFei·Du
|
||||
* @ClassName: ConnectServiceImpl
|
||||
* @Description: 服务实现类
|
||||
* @CreateTime: 2024/5/27 09:22
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class LoadBalanceServiceImpl implements LoadBalanceService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
|
||||
@Override
|
||||
public Result<MqttServerModel> getConnect(VehicleConnectionReq vehicleConnectionReq) {
|
||||
|
||||
|
||||
log.error(vehicleConnectionReq.toString());
|
||||
|
||||
|
||||
|
||||
//判断是否有游标key --count
|
||||
if (redisTemplate.hasKey("count")){
|
||||
|
||||
Integer count = Integer.valueOf(redisTemplate.opsForValue().get("count"));
|
||||
if (count == 100){
|
||||
redisTemplate.opsForValue().set("count",String.valueOf(0));
|
||||
}else {
|
||||
redisTemplate.opsForValue().set("count",String.valueOf(count + 1));
|
||||
}
|
||||
|
||||
//根据游标count获取服务IP
|
||||
String ip = redisTemplate.opsForList().index("ipList", count);
|
||||
//关联车辆和服务
|
||||
this.insertVinIp(new VinIp (vehicleConnectionReq.getVehicleVin(),ip));
|
||||
//响应信息
|
||||
return Result.success(new MqttServerModel("tcp://"+ip+":1883","test1"));
|
||||
}else {
|
||||
redisTemplate.opsForValue().set("count",String.valueOf(1));
|
||||
//根据游标count获取服务IP
|
||||
String ip = redisTemplate.opsForList().index("ipList", 0);
|
||||
//关联车辆和服务
|
||||
this.insertVinIp(new VinIp(vehicleConnectionReq.getVehicleVin(),ip));
|
||||
//响应信息
|
||||
return Result.success(new MqttServerModel("tcp://"+ip+":1883","test1"));
|
||||
}
|
||||
}
|
||||
|
||||
private void insertVinIp(VinIp vinIp) {
|
||||
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public void createConnect() {
|
||||
runEcsInstance("cn-zhangjiakou", "lt-8vbepqjihmawbkqcwkcm");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
package com.load.util;
|
||||
|
||||
import com.aliyun.ecs20140526.Client;
|
||||
import com.aliyun.ecs20140526.models.*;
|
||||
import com.aliyun.tea.TeaException;
|
||||
import com.aliyun.teaopenapi.models.Config;
|
||||
import com.aliyun.teautil.models.RuntimeOptions;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
||||
* ECS实例工具类
|
||||
* @author YunFei.Du
|
||||
* @date 9:30 2024/5/28
|
||||
*/
|
||||
@Log4j2
|
||||
public class ECSTool {
|
||||
|
||||
|
||||
/**
|
||||
* 创建ECS客户端
|
||||
* @return ECS客户端实例
|
||||
* @throws Exception 如果配置信息不正确或网络问题,将抛出异常
|
||||
* 注意:此方法用于演示,实际使用时请替换为安全的鉴权方式,如STS
|
||||
* 更多鉴权访问方式参考:https://help.aliyun.com/document_detail/378657.html
|
||||
*/
|
||||
public static Client createClient() throws Exception {
|
||||
// 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
|
||||
Config config = new Config()
|
||||
.setAccessKeyId("LTAI5tPTk3MFkmCGBbnQgmrM")
|
||||
.setAccessKeySecret("q7rLjxrI0SLBXlvNT4VmYcHCNCY2p6");
|
||||
// Endpoint 请参考 https://api.aliyun.com/product/Ecs
|
||||
config.endpoint = "ecs.cn-zhangjiakou.aliyuncs.com";
|
||||
return new Client(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建并运行ECS实例
|
||||
* @param regionId 地域ID
|
||||
* @param launchTemplateId 启动模板ID
|
||||
* @throws Exception 如果调用API时发生错误,将抛出异常
|
||||
*/
|
||||
public static void runEcsInstance(String regionId, String launchTemplateId) throws Exception {
|
||||
// 创建ECS客户端
|
||||
Client client = ECSTool.createClient();
|
||||
// 设置运行实例的请求参数
|
||||
RunInstancesRequest runInstancesRequest = new RunInstancesRequest()
|
||||
.setRegionId(regionId)
|
||||
.setLaunchTemplateId(launchTemplateId);
|
||||
// 创建运行选项
|
||||
RuntimeOptions runtime = new RuntimeOptions();
|
||||
|
||||
try {
|
||||
// 调用API运行实例
|
||||
client.runInstancesWithOptions(runInstancesRequest, runtime);
|
||||
} catch (Exception error) {
|
||||
// 处理API调用过程中出现的异常
|
||||
System.out.println(error.getMessage());
|
||||
if (error instanceof TeaException) {
|
||||
// 处理特定类型的异常,如TeaException
|
||||
TeaException teaError = (TeaException) error;
|
||||
System.out.println(teaError.getData().get("Recommend")); // 打印诊断推荐链接
|
||||
com.aliyun.teautil.Common.assertAsString(teaError.getMessage()); // 断言错误信息
|
||||
} else {
|
||||
// 处理其他类型的异常
|
||||
System.out.println(error.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁实例
|
||||
*/
|
||||
public static void runEcsRemove(String instanceId) throws Exception {
|
||||
// 创建ECS客户端
|
||||
Client client = ECSTool.createClient();
|
||||
DeleteInstanceRequest deleteInstanceRequest = new DeleteInstanceRequest ()
|
||||
.setInstanceId(instanceId);
|
||||
RuntimeOptions runtime = new RuntimeOptions();
|
||||
try {
|
||||
// 复制代码运行请自行打印 API 的返回值
|
||||
client.deleteInstanceWithOptions(deleteInstanceRequest, runtime);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询实例列表
|
||||
* @param regionId
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static List<String> FindInstance( String regionId) throws Exception {
|
||||
// 创建ECS客户端
|
||||
Client client = ECSTool.createClient ( );
|
||||
DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest ( )
|
||||
.setRegionId ( regionId );
|
||||
RuntimeOptions runtime = new RuntimeOptions ( );
|
||||
List< String > ipList = new ArrayList<> ( );
|
||||
try {
|
||||
// 复制代码运行请自行打印 API 的返回值
|
||||
DescribeInstancesResponse response = client.describeInstancesWithOptions ( describeInstancesRequest, runtime );
|
||||
|
||||
List< List< String > > ipListList = response.getBody ( ).instances.getInstance ( ).stream ( ).map ( instance -> instance.publicIpAddress.ipAddress ).collect ( Collectors.toList ( ) );
|
||||
for (List< String > strings : ipListList) {
|
||||
for (String ip : strings) {
|
||||
ipList.add ( ip );
|
||||
}
|
||||
System.out.println ( "------------------------" );
|
||||
}
|
||||
log.info ( "ipList: " + ipList ); // [39.100.89.218, 39.100.87.192]
|
||||
return ipList;
|
||||
} 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 );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
# 服务器相关
|
||||
|
||||
server:
|
||||
port: 82
|
||||
|
||||
spring:
|
||||
application:
|
||||
# 协议解析
|
||||
name: protocol-parsing
|
||||
rabbitmq:
|
||||
host: 111.229.102.61
|
||||
port: 5672
|
||||
username: guest
|
||||
password: guest
|
||||
virtualHost: /
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
password: dyf@123
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://111.229.102.61/car?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
|
||||
username: root
|
||||
password: dyf@123
|
Loading…
Reference in New Issue