feat():创建实例+获取实例ip

master
Yunfei Du 2024-05-28 18:16:08 +08:00
parent b27d094f93
commit a3968b7b3f
29 changed files with 1385 additions and 16 deletions

View File

@ -3,6 +3,8 @@
<component name="Encoding" defaultCharsetForPropertiesFiles="UTF-8">
<file url="file://$PROJECT_DIR$/VehicleSimulation/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/VehicleSimulation/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ZhiLian-LoadBalancing/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ZhiLian-LoadBalancing/src/main/resources" charset="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" />

View File

@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<list size="1">
<item index="0" class="java.lang.String" itemvalue="org.springframework.beans.factory.annotation.Autowired" />
</list>
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">

View File

@ -5,15 +5,12 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<relativePath>org.springframework.boot</relativePath>
<version>2.7.15</version>
<groupId>com.fei</groupId>
<artifactId>open-api</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.muyu</groupId>
<artifactId>VehicleSimulation</artifactId>
<version>1.0.0</version>
<artifactId>CarNet-VehicleSimulation</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
@ -23,8 +20,55 @@
</properties>
<description>
CarNet-VehicleSimulation车联网平台
</description>
<url>https://github.com/aliyun/alibabacloud-code-sample</url>
<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<developers>
<developer>
<id>aliyundeveloper</id>
<name>Aliyun SDK</name>
<email>aliyunsdk@aliyun.com</email>
</developer>
</developers>
<distributionManagement>
<snapshotRepository>
<id>sonatype-nexus-snapshots</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>sonatype-nexus-staging</id>
<url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<scm>
<connection></connection>
<developerConnection></developerConnection>
<url></url>
</scm>
<dependencies>
<!-- rabbitMQ -->
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
@ -95,5 +139,37 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-auth</artifactId>
<version>0.2.8-beta</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>ecs20140526</artifactId>
<version>5.1.8</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>tea-openapi</artifactId>
<version>0.3.3</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>tea-rpc</artifactId>
<version>0.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>darabonba-java-core</artifactId>
<version>0.2.8-beta</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,112 @@
package com;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
/**
* @ClassName demo_01
* @Description
* @Author YunFei.Du
* @Date 2024/5/27 14:44
*/
public class Demo1 {
/**
* HashMap
*
*
* @param args 使
*/
public static void main(String[] args) {
// 初始化一个HashMap存储节点ID及其对应的权重
HashMap< String, Double > nodeMap = new HashMap<> ( ){{
put ( "node_1",0.35 );
put ( "node_2",0.53 );
put ( "node_3",0.17 );
put ( "node_4",0.46 );
}};
// 将节点Map转换为NodeInfo对象的List
List< NodeInfo > nodeInfoList = nodeMap.entrySet ( )
.stream ( ).map ( NodeInfo::new )
.toList ( );
System.out.println (nodeInfoList );
// 计算所有节点权重的总和
double sum = nodeInfoList.stream ( )
.flatMapToDouble ( nodeInfo -> DoubleStream.of ( nodeInfo.getWeight ( ) ) )
.sum ( );
System.out.println (sum );
// 根据权重总和计算每个节点的特定比例
BigDecimal spec = new BigDecimal ( 100 ).divide ( new BigDecimal ( sum ), 2, BigDecimal.ROUND_HALF_UP );
// 使用计算出的比例,为每个节点分配整数数量
Map< String, Integer > collect = nodeInfoList.stream ( ).collect ( Collectors.toMap ( NodeInfo::getId,
nodeInfo -> spec.multiply ( BigDecimal.valueOf ( nodeInfo.getWeight ( ) ) ).setScale ( 0, RoundingMode.DOWN ).intValue (),
(o1, o2) -> o1 ) );
System.out.println (collect );
// 计算已分配节点数量的总和
int reduce = collect.values ( ).stream ( ).reduce ( 0, Integer::sum );
System.out.println (reduce );
// 计算剩余的未分配节点数量
int free=100-reduce;
// 为剩余的未分配节点分配数量
nodeInfoList.stream ()
.sorted ( Comparator.comparingInt ( o->o.getWeight ().intValue () ) )
.limit ( free )
.forEach ( nodeInfo -> {
collect.put ( nodeInfo.getId (),collect.get ( nodeInfo.getId ())+1 );
} );
System.out.println (collect );
// 准备一个字符串数组,以存储最终的节点分配结果
String[] nodeArray = new String[100];
int intArrCursor= -1;
// 将分配了数量的节点填充到字符串数组中,直到数组满或所有节点都已处理完毕
while (collect.size ()>1){
Iterator< Map.Entry< String, Integer > > specMapIterator = collect.entrySet ( ).iterator ( );
while (specMapIterator.hasNext ()){
Map.Entry< String, Integer > entry = specMapIterator.next ( );
Integer value = entry.getValue ( );
if (value>0){
nodeArray[++intArrCursor] = entry.getKey ( );
entry.setValue ( value-1 );
}
if (value==0){
specMapIterator.remove ();
}
}
}
System.out.println (collect );
System.out.println (Arrays.toString ( nodeArray ) );
}
}
class NodeInfo{
private String id;
private Double weight;
public NodeInfo (String id, Double weight){
this.id=id;
this.weight=weight;
}
public NodeInfo (Map.Entry<String,Double> entry){
this.id=entry.getKey ();
this.weight=entry.getValue ()*100;
}
public String getId(){
return id;
}
public Double getWeight(){
return weight;
}
}

View File

@ -0,0 +1,48 @@
//package com.muyu.config;
//
//import org.springframework.amqp.rabbit.connection.CorrelationData;
//import org.springframework.amqp.rabbit.core.RabbitTemplate;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.PostConstruct;
//
///**
// * 消息发送确认配置 消息发送到交换机的确认
// */
//@Component
//public class ConfirmCallbackConfig implements RabbitTemplate.ConfirmCallback {
//
// @Autowired
// private RabbitTemplate rabbitTemplate;
//
// /**
// * @PostContruct是spring框架的注解在⽅法上加该注解会在项⽬启动的时候执⾏该⽅法也可以理解为在spring容器初始化的时候执
// * @PostConstruct bean 被初始化的时候执行的方法的注解
// * @PreDestory bean 被销毁的时候执行的方法的注解
// */
// @PostConstruct
// public void init() {
// rabbitTemplate.setConfirmCallback(this);
// }
//
// /**
// * 交换机不管是否收到消息的一个回调方法
// *
// * @param correlationData 消息相关数据
// * @param ack 交换机是否收到消息
// * @param cause 失败原因
// */
// @Override
// public void confirm(CorrelationData correlationData, boolean ack, String cause) {
// if (ack) {
// // 消息投递到 broker 的状态true表示成功
// System.out.println("消息发送成功!");
// } else {
// // 发送异常
// System.out.println("发送异常原因 = " + cause);
// // TODO 可以将消息 内容 以及 失败的原因 记录到 日志表中
// }
// }
//
//}

View File

@ -0,0 +1,53 @@
//package com.muyu.config;
//
//import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
//import org.springframework.amqp.rabbit.connection.ConnectionFactory;
//import org.springframework.amqp.rabbit.core.RabbitAdmin;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//
///**
// * RabbitAdmin是RabbitMQ的一个Java客户端库它提供了管理RabbitMQ资源的功能。它是通过与RabbitMQ服务器进行交互来执行管理操作的。
// */
//@Configuration
//public class RabbitAdminConfig {
//
// @Value("${spring.rabbitmq.host}")
// private String host;
// @Value("${spring.rabbitmq.username}")
// private String username;
// @Value("${spring.rabbitmq.password}")
// private String password;
// @Value("${spring.rabbitmq.virtualhost}")
// private String virtualhost;
//
// /**
// * 构建 RabbitMQ的连接工厂
// * @return
// */
// @Bean
// public ConnectionFactory connectionFactory() {
// CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
// connectionFactory.setAddresses(host);
// connectionFactory.setUsername(username);
// connectionFactory.setPassword(password);
// connectionFactory.setVirtualHost(virtualhost);
// // 配置发送确认回调时次配置必须配置否则即使在RabbitTemplate配置了ConfirmCallback也不会生效
// connectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
// connectionFactory.setPublisherReturns(true);
// return connectionFactory;
// }
//
// /**
// * 自己初始化 RabbitAdmin
// * @param connectionFactory
// * @return
// */
// @Bean
// public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
// RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
// rabbitAdmin.setAutoStartup(true);
// return rabbitAdmin;
// }
//}

View File

@ -0,0 +1,15 @@
//package com.muyu.config;
//
//import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
//import org.springframework.amqp.support.converter.MessageConverter;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//
//@Configuration
//public class RabbitmqConfig {
// // 消息转换配置
// @Bean
// public MessageConverter jsonMessageConverter() {
// return new Jackson2JsonMessageConverter();
// }
//}

View File

@ -0,0 +1,34 @@
//package com.muyu.config;
//
//import org.springframework.amqp.core.ReturnedMessage;
//import org.springframework.amqp.rabbit.core.RabbitTemplate;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.PostConstruct;
//
///**
// * 消息发送到队列的确认 一旦消息发送到队列失败 则会执行 returnedMessage 方法
// */
//@Component
//public class ReturnCallbackConfig implements RabbitTemplate.ReturnsCallback {
//
// @Autowired
// private RabbitTemplate rabbitTemplate;
//
// @PostConstruct // @PostContruct是spring框架的注解在⽅法上加该注解会在项⽬启动的时候执⾏该⽅法也可以理解为在spring容器初始化的时候执
// public void init() {
// rabbitTemplate.setReturnsCallback(this);
// }
//
// /**
// * 消息发送到 队列失败 执行的 方法
// * @param returnedMessage the returned message and metadata.
// */
// @Override
// public void returnedMessage(ReturnedMessage returnedMessage) {
// System.out.println("消息" + returnedMessage.getMessage().toString() + "被交换机" + returnedMessage.getExchange() + "回退!"
// + "退回原因为:" + returnedMessage.getReplyText());
// // 回退了所有的信息,可做补偿机制 记录到 数据库
// }
//}

View File

@ -0,0 +1,22 @@
package com.muyu.constants;
/**
* @ClassName RabbitMQOneConstants
* @Description
* @Author YunFei.Du
* @Date 2024/5/27 22:04
*/
public class RabbitMQOneConstants {
/**
*
*/
public static final String SEND_CODE="send_code_queue";
//发送短消息队列名称
public static final String SEND_SHORT_MESSAGE_QUEUE_NAME = "send_short_message";
//查看的日志队列名称
public static final String QUERY_LOG_QUEUE_NAME = "query_log_message";
}

View File

@ -0,0 +1,25 @@
package com.muyu.consumer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* @ClassName ConnectionConsumer
* @Description
* @Author YunFei.Du
* @Date 2024/5/27 21:57
*/
@Component
public class ConnectionConsumer {
@RabbitListener(queuesToDeclare = @Queue(name = "ADD_LOG_AAA"))
public void receive(Message message, Channel channel) {
ObjectMapper mapper = new ObjectMapper ( );
// mapper.convertValue ( messageConverter. )
}
}

View File

@ -12,6 +12,16 @@ import lombok.Data;
@Data
@AllArgsConstructor
public class ServerNode {
/**
* ip
*/
private String ip;
/**
*
*/
private Integer port;
/**
*
*/
private Double loadPercentage;
}

View File

@ -0,0 +1,50 @@
package com.muyu.loadcenter.common;
import com.muyu.domain.model.MqttServerModel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @ClassName AccessPool
* @Description
* @Author YunFei.Du
* @Date 2024/5/27 22:39
*/
@Data
@NoArgsConstructor
@Log4j2
public class AccessPool {
private static Integer sequence = 0;
private static Map<String, MqttServerModel > accessPools = new HashMap<> ();
public static void initAccessPools(List<MqttServerModel> mqttServerModels){
accessPools = mqttServerModels.stream().collect( Collectors.toMap(MqttServerModel::getBroker, Function.identity()));
}
public static void addAccessPool(MqttServerModel mqttServerModel){
accessPools.put(mqttServerModel.getBroker(),mqttServerModel);
}
public static void lookAccessPools(){
accessPools.forEach((k,v)->{
log.info("key:"+k+" value:"+v.toString());
});
}
public static MqttServerModel getMqttServerModel(){
if (sequence == accessPools.size()){
sequence = 0;
}
Set<String> strings = accessPools.keySet();
return accessPools.get(strings.toArray()[sequence++]);
}
}

View File

@ -0,0 +1,14 @@
package com.muyu.service;
import com.muyu.common.Result;
/**
* @ClassName LoadCenterService
* @Description
* @Author YunFei.Du
* @Date 2024/5/27 22:35
*/
public interface LoadCenterService {
Result getDescribeInstances();
}

View File

@ -0,0 +1,29 @@
package com.muyu.service.impl;
import com.muyu.common.Result;
import com.muyu.service.LoadCenterService;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
import static com.muyu.utils.ECSTool.runEcsInstance;
/**
* @ClassName LoadCenterServiceImpl
* @Description
* @Author YunFei.Du
* @Date 2024/5/27 22:36
*/
@Service
@Log4j2
public class LoadCenterServiceImpl implements LoadCenterService {
@Override
public Result getDescribeInstances() {
try {
runEcsInstance("cn-zhangjiakou", "lt-8vbepqjihmawbkqcwkcm");
return Result.success ();
} catch (Exception e) {
log.error ( "getDescribeInstances error:{}", e );
throw new RuntimeException ( e );
}
}
}

View File

@ -142,8 +142,8 @@ public class VechileServiceImpl extends ServiceImpl<VehicleMapper, Vehicle> impl
public ServerNode assignServerNode(String vehicleId) {
// 这里为了简化,我们随机选择一个节点
List< ServerNode > serverNodes = Arrays.asList (
new ServerNode ( "192.168.1.1", 8080 ),
new ServerNode ( "192.168.1.2", 8081 )
new ServerNode ( "192.168.1.1", 8080,0.23 ),
new ServerNode ( "192.168.1.2", 8081 ,0.50)
);
if (serverNodes.isEmpty()) {

View File

@ -0,0 +1,99 @@
package com.muyu.utils;
import com.aliyun.ecs20140526.Client;
import com.aliyun.ecs20140526.models.RunInstancesRequest;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import lombok.SneakyThrows;
import okhttp3.*;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
/**
* ECSECS
*/
public class ECSTool {
/**
* ECS
* @return ECS
* @throws Exception
* 使STS
* 访https://help.aliyun.com/document_detail/378657.html
*/
public static Client createClient() throws Exception {
// 配置ECS客户端的基本信息包括访问密钥和endpoint
Config config = new Config()
.setAccessKeyId("LTAI5tPTk3MFkmCGBbnQgmrM") // 示例Access Key ID实际使用时应从环境变量获取
.setAccessKeySecret("q7rLjxrI0SLBXlvNT4VmYcHCNCY2p6"); // 示例Access Key Secret实际使用时应从环境变量获取
config.endpoint = "ecs.cn-zhangjiakou.aliyuncs.com"; // 设置ECS服务的访问地址
// 创建并返回ECS客户端实例
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 main(String[] args) throws Exception {
List<String> argsList = Arrays.asList(args);
// 示例调用,实际使用时需要传入 区域 ID 和 启动模板 ID
runEcsInstance("cn-zhangjiakou", "lt-8vbepqjihmawbkqcwkcm");
}
// @SneakyThrows
// public static void main(String[] args) {
// OkHttpClient client = new OkHttpClient.Builder()
// .build();
//
// // 注意GET请求通常不需要MediaType和RequestBody
// Request request = new Request.Builder()
// .url("http://fluxmq.muyu.icu/public/cluster")
// .method("GET", null) // 对于GET请求通常不需要设置RequestBody所以传入null
// .addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
// .addHeader("Access-Token", "2f68dbbf-519d-4f01-9636-e2421b68f379") // 确保使用正确的头部名称和令牌值
// .build();
//
// try (Response response = client.newCall(request).execute()) {
// if (!response.isSuccessful()) {
// throw new IOException("Unexpected code " + response);
// } else {
// // 打印响应体
// System.out.println(response );
// }
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
}

View File

@ -1,6 +1,18 @@
server:
port: 82
spring:
rabbitmq:
host: 111.229.102.61
port: 5672
username: guest
password: guest
virtual-host: /
listener:
simple:
prefetch: 1
acknowledge-mode: manual # 接收 消费 消息手动确认
direct:
acknowledge-mode: manual # 接收 消费 消息手动确认
mvc:
static-path-pattern: /static/**
@ -86,7 +98,7 @@ forest:
# 服务器配置
mqtt:
server:
host: tcp://47.92.65.101:1883
host: tcp://39.100.87.192:1883
topic: test1
admin:
host: http://127.0.0.1:${server.port}

View File

@ -0,0 +1,60 @@
<?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>
<parent>
<groupId>com.fei</groupId>
<artifactId>open-api</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>ZhiLian-LoadBalancing</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>ecs20140526</artifactId>
<version>5.1.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.47</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>3.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,12 @@
package com.zhiLian;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LoadBalancingApplication {
public static void main(String[] args) {
SpringApplication.run ( LoadBalancingApplication.class );
}
}

View File

@ -0,0 +1,83 @@
package com.zhiLian.common;
import lombok.Data;
import java.io.Serializable;
@Data
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
* =================================================================================================================
*/
public static final int SUCCESS = ResultConstants.SUCCESS;
/**
*
* =================================================================================================================
*/
public static final int FAIL = ResultConstants.ERROR;
/**
*
* =================================================================================================================
*/
private int code;
/**
*
* =================================================================================================================
*/
private String msg;
/**
*
* =================================================================================================================
*/
private T data;
public static <T> Result<T> success() {
return restResult(null, SUCCESS, ResultConstants.SUCCESS_MSG);
}
public static <T> Result<T> success(T data) {
return restResult(data, SUCCESS, ResultConstants.SUCCESS_MSG);
}
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, ResultConstants.ERROR_MSG);
}
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, ResultConstants.ERROR_MSG);
}
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);
}
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;
}
}

View File

@ -0,0 +1,22 @@
package com.zhiLian.common;
public class ResultConstants {
/**
*
* =================================================================================================================
*/
public static final Integer SUCCESS = 200;
public static final String SUCCESS_MSG = "操作成功";
/**
*
* =================================================================================================================
*/
public static final Integer ERROR = 500;
public static final String ERROR_MSG = "操作异常";
}

View File

@ -0,0 +1,67 @@
package com.zhiLian.controller;
import com.zhiLian.common.Result;
import com.zhiLian.service.LoadBalanceService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @ClassName LoadBalanceController
* @Description
* @Author YunFei.Du
* @Date 2024/5/28 9:12
*/
@RestController
@RequestMapping("loadBalance")
@Log4j2
public class LoadBalanceController {
@Autowired
private LoadBalanceService loadBalanceService;
/**
*
*/
@GetMapping("/createConnect")
public void createConnect() {
loadBalanceService.createConnect();
log.info("创建实例成功");
}
// /**
// * 停止实例
// */
// @GetMapping("/stopConnect")
// public void stopConnect(@RequestParam String instanceId) {
// loadBalanceService.stopConnect(instanceId);
// log.info("停止实例成功");
// }
/**
*
* instanceId id
*/
@GetMapping("/removeConnect")
public void removeConnect(@RequestParam String instanceId) {
loadBalanceService.removeConnect(instanceId);
log.info("销毁实例成功");
}
/**
*
*/
@GetMapping("/getIpList")
public Result< List<String> > getIpList() {
List<String> ipList = loadBalanceService.getIpList();
// ipListThread = ipList;
return Result.success(ipList);
}
}

View File

@ -0,0 +1,236 @@
package com.zhiLian.resp;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
*
* @author YunFei.Du
* @date 9:10 2024/5/27
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ConnectResp {
/**
*
*/
private String nodeName;
/**
*
*/
private String version;
/**
*
*/
private String startJvmTime;
/**
* ID
*/
private String clusterId;
/**
* HTTP
*/
private String httpUrl;
/**
* MQTTS
*/
private String mqttUrl;
/**
* websocket
*/
private String websocketUrl;
private FlowInfo flowInfo;
/**
*
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
private static class FlowInfo {
/**
*
*/
private String writeBytesHistory;
/**
*
*/
private String readBytesHistory;
/**
*
*/
private String lastReadThroughput;
/**
*
*/
private String lastWriteThroughput;
/**
*
*/
private String realWriteBytes;
}
public CpuInfo cpuInfo;
/**
* cpu使
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class CpuInfo {
/**
* CPU使
*/
private String cSys;
/**
*
*/
private String idle;
/**
* I/O
*/
private String iowait;
/**
* 使
*/
private String user;
/**
* CPU
*/
private Integer cpuNum;
}
public JvmInfo jvmInfo;
/**
* jvm使
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class JvmInfo {
/**
* JAVA
*/
private String jdkHome;
/**
*
*/
private String heapCommit;
/**
*
*/
private String heapMax;
/**
* 线
*/
private Integer threadCount;
/**
* (
*/
private String fileDescriptors;
/**
*
*/
private String noHeapMax;
/**
*
*/
private String noHeapInit;
/**
* JDK
*/
private String jdkVersion;
/**
*
*/
private String heapInit;
/**
* 使
*/
private String heapUsed;
/**
*
*/
private String noHeapCommit;
/**
* 使
*/
private String noHeapUsed;
}
public MqttInfo mqttInfo;
/**
* MQTT
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class MqttInfo {
/**
*
*/
private Integer connectEventSize;
/**
*
*/
private Integer subscribeEventSize;
/**
*
*/
private Integer publishRetryEventSize;
/**
*
*/
private Integer topicSize;
/**
*
*/
private Integer disconnectEventSize;
/**
*
*/
private Integer subscribeSize;
/**
*
*/
private Integer publishEventSize;
/**
*
*/
private Integer closeEventSize;
/**
*
*/
private Integer connectSize;
/**
*
*/
private Integer retainSize;
/**
*
*/
private Integer unSubscribeEventSize;
}
}

View File

@ -0,0 +1,21 @@
package com.zhiLian.service;
import java.util.List;
/**
* @ClassName LoadBalanceService
* @Description
* @Author YunFei.Du
* @Date 2024/5/28 9:25
*/
public interface LoadBalanceService {
void createConnect();
void removeConnect(String instanceId);
void stopConnect(String instanceId);
List< String> getIpList();
}

View File

@ -0,0 +1,55 @@
package com.zhiLian.service.impl;
import com.aliyun.ecs20140526.models.DescribeInstancesResponse;
import com.aliyun.ecs20140526.models.ModifySecurityGroupRuleResponse;
import com.google.gson.Gson;
import com.zhiLian.service.LoadBalanceService;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
import java.util.List;
import static com.zhiLian.utils.ECSTool.*;
/**
* @ClassName LoadBalanceService
* @Description
* @Author YunFei.Du
* @Date 2024/5/28 9:25
*/
@Service
@Log4j2
public class LoadBalanceServiceImpl implements LoadBalanceService {
@SneakyThrows
@Override
public void createConnect() {
runEcsInstance("cn-zhangjiakou", "lt-8vbepqjihmawbkqcwkcm");
}
@Override
public void removeConnect(String instanceId) {
try {
runEcsStop (instanceId);
} catch (Exception e) {
log.error ( "getDescribeInstances error:{}", e );
throw new RuntimeException ( e );
}
}
@SneakyThrows
@Override
public void stopConnect(String instanceId) {
runEcsRemove ( instanceId );
}
@SneakyThrows
@Override
public List< String > getIpList() {
FindInstance ( "cn-zhangjiakou" );
return null;
}
}

View File

@ -0,0 +1,175 @@
package com.zhiLian.utils;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.aliyun.ecs20140526.Client;
import com.aliyun.ecs20140526.models.*;
import com.aliyun.tea.TeaException;
import com.aliyun.tea.TeaModel;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.Common;
import com.aliyun.teautil.models.RuntimeOptions;
import lombok.extern.log4j.Log4j2;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* 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 {
// 配置ECS客户端的基本信息包括访问密钥和endpoint
Config config = new Config()
.setAccessKeyId("LTAI5tPTk3MFkmCGBbnQgmrM") // 示例Access Key ID实际使用时应从环境变量获取
.setAccessKeySecret("q7rLjxrI0SLBXlvNT4VmYcHCNCY2p6"); // 示例Access Key Secret实际使用时应从环境变量获取
config.endpoint = "ecs.cn-zhangjiakou.aliyuncs.com"; // 设置ECS服务的访问地址
// 创建并返回ECS客户端实例
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 runEcsStop(String instanceId) throws Exception {
// 创建ECS客户端
Client client = ECSTool.createClient();
StopInstanceRequest stopInstanceRequest = new StopInstanceRequest ()
.setInstanceId(instanceId);
RuntimeOptions runtime = new RuntimeOptions();
try {
// 复制代码运行请自行打印 API 的返回值
client.stopInstanceWithOptions(stopInstanceRequest, runtime);
} catch (TeaException 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);
}
}
public static void 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 );
} 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);
}
}
}

View File

@ -0,0 +1,2 @@
server:
port: 84

40
pom.xml
View File

@ -10,11 +10,41 @@
<packaging>pom</packaging>
<modules>
<module>VehicleSimulation</module>
<module>ZhiLian-LoadBalancing</module>
</modules>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.6.2</version>
<relativePath/>
</parent>
<!-- 依赖声明 -->
<dependencyManagement>
<dependencies>
<!-- SpringCloud 微服务 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringCloud Alibaba 微服务 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Alibaba Nacos 配置 -->
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>2.0.4</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@ -1,4 +1,4 @@
package com.fei;
package com.zhiLian;
public class Main {
public static void main(String[] args) {