黄大举更新

master
黄大举 2024-04-18 21:55:46 +08:00
parent 0cd280e8f1
commit 92bec83a85
23 changed files with 1013 additions and 195 deletions

46
.idea/.gitignore vendored 100644
View File

@ -0,0 +1,46 @@
######################################################################
# Build Tools
.gradle
/build/
!gradle/wrapper/gradle-wrapper.jar
target/
!.mvn/wrapper/maven-wrapper.jar
######################################################################
# IDE
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### JRebel ###
rebel.xml
### NetBeans ###
nbproject/private/
build/*
nbbuild/
dist/
nbdist/
.nb-gradle/
######################################################################
# Others
*.log
*.xml.versionsBackup
*.swp
!*/build/*.java
!*/build/*.html
!*/build/*.xml

View File

@ -62,7 +62,11 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<!-- &lt;!&ndash; SpringCloud Openfeign &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-openfeign</artifactId>-->
<!-- </dependency>-->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

View File

@ -4,11 +4,11 @@ import com.aliyun.ecs20140526.Client;
import com.aliyun.ecs20140526.models.*; import com.aliyun.ecs20140526.models.*;
import com.aliyun.tea.TeaException; import com.aliyun.tea.TeaException;
import com.aliyun.teautil.models.RuntimeOptions; import com.aliyun.teautil.models.RuntimeOptions;
import com.muyu.loadCenter.aliyun.config.AliConfig; import com.muyu.loadCenter.config.AliConfig;
import com.muyu.loadCenter.aliyun.utils.UserUtil; import com.muyu.loadCenter.aliyun.utils.UserUtil;
import com.muyu.loadCenter.domain.EcsInstanceInfo; import com.muyu.loadCenter.domain.EcsInstanceInfo;
import com.muyu.loadCenter.aliyun.config.InstanceConfig; import com.muyu.loadCenter.config.InstanceConfig;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;

View File

@ -1,4 +1,4 @@
package com.muyu.loadCenter.aliyun.config; package com.muyu.loadCenter.config;
import com.aliyun.ecs20140526.Client; import com.aliyun.ecs20140526.Client;
import com.aliyun.teaopenapi.models.Config; import com.aliyun.teaopenapi.models.Config;

View File

@ -1,4 +1,4 @@
package com.muyu.loadCenter.aliyun.config; package com.muyu.loadCenter.config;
import lombok.Data; import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;

View File

@ -1,4 +1,4 @@
package com.muyu.loadCenter.aliyun.config;//package com.muyu.business.domain.config; package com.muyu.loadCenter.config;//package com.muyu.business.domain.config;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;

View File

@ -1,41 +0,0 @@
package com.muyu.loadCenter.controller;
import com.muyu.loadCenter.redis.service.RedisService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 线
* @Author HuangDaJu
* @Date 2024/4/17 21:28
* @Version 1.0
*/
@Log4j2
@RestController
@RequestMapping("downLine")
public class DownLineController {
@Autowired
private RedisService redisService;
@PostMapping("/carDownLine/{vin}")
public void getVinDownLine(@PathVariable String vin) throws Exception {
String nodeId = redisService.getCacheObject("delete:" + vin);
redisService.deleteObject("delete:"+vin);
redisService.deleteCacheSet("release:"+nodeId,vin);
log.info("车辆下线成功");
}
}

View File

@ -0,0 +1,49 @@
package com.muyu.loadCenter.controller;
import com.muyu.loadCenter.domain.Result;
import com.muyu.loadCenter.service.GatewayLoadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @ProjectName: load_center
* @PackageName: com.muyu.loadCenter.controller
* @Description ->
* @Author HuangDaJu
* @Date 2024/4/18 14:14
* @Version 1.0
*/
@RestController
@RequestMapping("/gateway")
public class GatewayController {
@Autowired
private GatewayLoadService gatewayLoadService;
/**
* 线,id
*/
@GetMapping("/load/node")
public Result<String> loadNode(){
return Result.success(gatewayLoadService.loadNode());
}
/**
* 30
*
*
*/
@Scheduled(cron = "0/5 * * * * ?")
public void scheduleECS() throws Exception {
gatewayLoadService.scheduleECS();
}
}

View File

@ -0,0 +1,57 @@
package com.muyu.loadCenter.controller;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.muyu.loadCenter.domain.Result;
import com.muyu.loadCenter.service.GatewayVehicleService;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Map;
/**
* @Description 线
* @Author HuangDaJu
* @Date 2024/4/18 18:37
* @Version 1.0
*/
@RestController
@RequestMapping("/vehicle")
public class GatewayVehicleController {
@Autowired
private GatewayVehicleService gatewayVehicleService;
/**
* 线
*/
@GetMapping("/load/topLine/{vin}")
public Result<String> topLine(@PathVariable String vin){
return gatewayVehicleService.topLine(vin);
}
/**
* 线
*/
@GetMapping("/load/downLine/{vin}")
public void loadDownLine(@PathVariable String vin){
gatewayVehicleService.loadDownLine(vin);
}
}

View File

@ -1,148 +0,0 @@
package com.muyu.loadCenter.controller;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.muyu.loadCenter.aliyun.service.AliYunEcsService;
import com.muyu.loadCenter.domain.EcsInstanceInfo;
import com.muyu.loadCenter.domain.Result;
import com.muyu.loadCenter.service.ReleaseEcsDownLine;
import lombok.extern.log4j.Log4j2;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.muyu.loadCenter.redis.service.RedisService;
import org.springframework.web.client.RestTemplate;
import java.util.Set;
/**
*
* @Author HuangDaJu
* @Date 2024/4/13 08:43
*/
@Component
@Log4j2
public class LoadCenterController {
// 用于临时统计连接数以判断是否需要扩容的变量
int aa=0;
// 临时变量,无特定用途(根据现有代码)
int bb=0;
// Redis字符串模板用于与Redis进行交互
@Autowired
private RedisService redisService; // Redis服务封装了与Redis操作相关的功能
@Autowired
private AliYunEcsService aliYunEcsService; // 阿里云ECS服务用于管理云服务器
@Autowired
private RestTemplate restTemplate;
@Autowired
private ReleaseEcsDownLine releaseEcsDownLine;// 用于与其他服务进行HTTP交互的模板
/**
* 30
*
*
*/
@Scheduled(cron = "0/5 * * * * ?")
public void scheduleECS() throws Exception {
// 客户端初始化
OkHttpClient client = new OkHttpClient();
// 从Redis获取服务器IP集合
Set<String> ipCacheSet = redisService.getCacheZSet("ECS");
log.info("共有个"+ipCacheSet.size()+"服务器");
// 遍历每台服务器进行负载检查
for (String ip : ipCacheSet) {
// 构建请求URL和请求头
String URL = "http://"+ip+":8080/public/cluster";
Request request = new Request.Builder()
.url(URL)
.get()
.addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
.addHeader("Accesstoken", "")
.build();
try {
Response response = client.newCall(request).execute();
// 解析响应数据
JSONArray jsonArray = JSONArray.parseArray(response.body().string());
JSONObject jsonObject = jsonArray.getJSONObject(0);
JSONObject mqttInfo = jsonObject.getJSONObject("mqttInfo");
int connectSize = mqttInfo.getIntValue("connectSize");
log.info("服务器:"+ip+"-车辆连接数:"+connectSize);
// 更新Redis中服务器的连接数ZSet数据类型
redisService.setCacheZSet("ECS", ip, connectSize);
// 根据连接数判断是否需要进行扩容或缩容
if (connectSize >= 6) {
aa++;
// 当满足扩容条件时,记录日志并执行扩容操作
if (aa == ipCacheSet.size()) {
log.info("需要扩容");
// 调用阿里云ECS服务创建新实例
String instanceId = aliYunEcsService.runInstances();
log.info("扩容的节点ip为" + instanceId);
// 休眠5秒以确保新实例创建完成
Thread.sleep(5000);
// 获取新实例信息并将其持久化到本地数据库
EcsInstanceInfo ecsInstanceInfo = aliYunEcsService.selectList(instanceId);
//String数据类型:创建好并查询的对象转换为JSON字符串信息存入redis第一个数据类型 先存入redis 确保正常运行了在假如Zset表
redisService.setCacheObject("ecsInstance:"+ecsInstanceInfo.getPublicIpAddress(), ecsInstanceInfo.getInstanceId());
//这里模拟(也可以在别的类里完成) ECS创建成功后服务器发送一条消息服务器正常启动mq可以正常使用存入redis
redisService.setCacheZSet("ECS", ecsInstanceInfo.getPublicIpAddress(), 0);
// String url = "http://127.0.0.1:9006/ecsInstance/add";
// restTemplate.postForObject(url, ecsInstanceInfo, Result.class);
log.info("实例信息持久化本地");
// 将新实例的IP和ID存入Redis
log.info("实例id和公网ip存入redis");
aa = 0; // 重置计数器
}
}
else if (connectSize <= 2) {
//删除ECS里面的ip车辆再次上线找不到这个要缩容的服务器让找不到
redisService.deleteCacheZset("ECS" ,ip);
// 缩容逻辑:删除连接数过低的服务器实例
// String url = "http://127.0.0.1:9006/ecsInstance/select/" + ip;
// Result result = restTemplate.postForObject(url, null, Result.class);
// String instanceId = (String) result.getData();
releaseEcsDownLine.releaseEcsDownLine(ip);
// aliYunEcsService.releaseECS(instanceId); // 释放ECS实例
// Long i = redisService.deleteCacheZset("ECS", ip);// 从Redis中删除该服务器的记录
log.info("连接数小于2,服务器缩容:" + ip);
aa = 0; // 重置计数器
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,27 @@
package com.muyu.loadCenter.gateway.abs;
import com.muyu.loadCenter.redis.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @ProjectName: load_center
* @PackageName: com.muyu.loadCenter.gateway.abs
* @Description
* @Author HuangDaJu
* @Date 2024/4/18 11:37
* @Version 1.0
*/
public abstract class GatewayCacheAbs<K> {
@Autowired
public RedisService redisService;
public abstract String getPre();
public String encode(K key){
return getPre()+key;
}
}

View File

@ -0,0 +1,65 @@
package com.muyu.loadCenter.gateway.cache;
import com.muyu.loadCenter.gateway.abs.GatewayCacheAbs;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Description redis 100
* @Author HuangDaJu
* @Date 2024/4/18 11:35
* @Version 1.0
*/
@Component
public class GatewayLoadNodeCache extends GatewayCacheAbs<String> {
private final static String gatewayLoadNodeKey="node";
@Override
public String getPre() {
return "gateway:lode:";
}
/**
*
* @param nodeList
*/
public void put(List<String> nodeList){
redisService.deleteObject(encode(gatewayLoadNodeKey));
redisService.setCacheList(encode(gatewayLoadNodeKey),nodeList);
}
/**
*
* @return
*/
public List<String> get(){
return redisService.getCacheList(encode(gatewayLoadNodeKey));
}
/**
*
* @param index
* @return
*/
public String getByIndex(Long index){
if (index ==null || index > 100){
throw new RuntimeException("下标违法0-100");
}
return redisService.getCacheListValue(encode(gatewayLoadNodeKey),index);
}
}

View File

@ -0,0 +1,63 @@
package com.muyu.loadCenter.gateway.cache;
import com.muyu.loadCenter.gateway.abs.GatewayCacheAbs;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* @Description series
* @Author HuangDaJu
* @Date 2024/4/18 11:57
* @Version 1.0
*/
@Component
public class GatewayLoadSeriesCache extends GatewayCacheAbs<String> {
private final static String gatewayLoadSeriesKey = "series";
@Override
public String getPre () {
return "gateway:load:";
}
/**
*
* @return
*/
public Long incrementAndGet(){
return redisService.increment(encode(gatewayLoadSeriesKey), 1L);
}
/**
* bean
*/
@PostConstruct
public void init(){
redisService.setCacheObject(encode(gatewayLoadSeriesKey), 0);
}
/**
*
* @return
*/
public Long get(){
return redisService.getCacheObject(encode(gatewayLoadSeriesKey));
}
/**
*
*/
public void reset(){
this.init();
}
}

View File

@ -0,0 +1,59 @@
package com.muyu.loadCenter.gateway.cache;
import com.muyu.loadCenter.gateway.abs.GatewayCacheAbs;
import com.muyu.loadCenter.gateway.model.GatewayNodeInfo;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Description String info
* @Author HuangDaJu
* @Date 2024/4/18 14:08
* @Version 1.0
*/
@Component
public class GatewayNodeCache extends GatewayCacheAbs<String> {
private final static String gatewayNodeCache = "info:";
@Override
public String getPre() {
return "gateway:node:";
}
/**
*
* @param gatewayNodeInfo
*/
public void put(String ip,GatewayNodeInfo gatewayNodeInfo){
redisService.setCacheObject(encode(gatewayNodeCache)+ip,gatewayNodeInfo);
}
/**
*
*/
public GatewayNodeInfo get(String ip){
return redisService.getCacheObject(encode(gatewayNodeCache)+ip);
}
public List<GatewayNodeInfo> get(){
return redisService.getCacheObject(encode(gatewayNodeCache));
}
/**
*
*/
public void remove(String nodeId){
redisService.deleteObject(encode(nodeId));
}
}

View File

@ -0,0 +1,47 @@
package com.muyu.loadCenter.gateway.cache;
import com.muyu.loadCenter.gateway.abs.GatewayCacheAbs;
import org.springframework.stereotype.Component;
/**
* @Description vin
* @Author HuangDaJu
* @Date 2024/4/18 19:13
* @Version 1.0
*/
@Component
public class GatewayNodeSetVinCache extends GatewayCacheAbs<String> {
private final static String gatewayNodeSetVinCache="many:";
@Override
public String getPre() {
return "gateway:node:";
}
/**
* vin
*/
public void put(String node,String vin){
redisService.setCacheSet(encode(gatewayNodeSetVinCache)+node,vin);
}
/**
* vin
*/
public void remove(String nodeId,String vin){
redisService.deleteCacheSet(encode(gatewayNodeSetVinCache)+nodeId,vin);
}
}

View File

@ -0,0 +1,50 @@
package com.muyu.loadCenter.gateway.cache;
import com.muyu.loadCenter.gateway.abs.GatewayCacheAbs;
import org.springframework.stereotype.Component;
/**
* @Description 线+vin:id
* @Author HuangDaJu
* @Date 2024/4/18 17:20
* @Version 1.0
*/
@Component
public class GatewayVehicleNode extends GatewayCacheAbs<String> {
private final static String gatewayCarBusinessKey="business:";
@Override
public String getPre() {
return "gateway:car:";
}
/**
* vin gateway:car:business+vin, id
*/
public void put(String vin,String nodeId){
redisService.setCacheObject(encode(gatewayCarBusinessKey)+vin,nodeId);
}
/**
* vin gateway:car:business
*/
public void remove(String vin){
redisService.deleteObject(encode(gatewayCarBusinessKey)+vin);
}
/**
* nodeId
*/
public String get(String vin){
return redisService.getCacheObject(encode(gatewayCarBusinessKey)+vin);
}
}

View File

@ -0,0 +1,55 @@
package com.muyu.loadCenter.gateway.cache;
import com.muyu.loadCenter.gateway.abs.GatewayCacheAbs;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
/**
* @Description +
* @Author HuangDaJu
* @Date 2024/4/18 15:32
* @Version 1.0
*/
@Component
public class GatewayZSetNodeCache extends GatewayCacheAbs<String> {
private final static String gatewayZSetCount="count";
@Override
public String getPre() {
return "gateway:zSet:";
}
/**
* zset
* @return
*/
public Map<Object, Double> get(){
return redisService.getCacheZSetScore(encode(gatewayZSetCount));
}
/**
* 线
*/
public void put(String nodeId ,Integer onlineVehicle){
redisService.setCacheZSet(encode(gatewayZSetCount),nodeId,onlineVehicle);
}
/**
* zset,
*/
public void remove(String nodeId){
redisService.deleteCacheZset(encode(gatewayZSetCount),nodeId);
}
}

View File

@ -0,0 +1,38 @@
package com.muyu.loadCenter.gateway.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @ProjectName: load_center
* @PackageName: com.muyu.loadCenter.gateway.model
* @Description
* @Author HuangDaJu
* @Date 2024/4/18 11:28
* @Version 1.0
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class GatewayNodeInfo {
/**
* Id
*/
private String nodeId;
/**
* ip
*/
private String publicIdAddress;
/**
* ip
*/
private String privateIdAddress;
}

View File

@ -0,0 +1,24 @@
package com.muyu.loadCenter.service;
/**
* @ProjectName: load_center
* @PackageName: com.muyu.loadCenter.service
* @Description TODO
* @Author HuangDaJu
* @Date 2024/4/18 14:16
* @Version 1.0
*/
public interface GatewayLoadService {
/**
*
* @return
*/
String loadNode();
void scheduleECS();
}

View File

@ -0,0 +1,26 @@
package com.muyu.loadCenter.service;
import com.muyu.loadCenter.domain.Result;
/**
* @ProjectName: load_center
* @PackageName: com.muyu.loadCenter.service
* @Description TODO
* @Author HuangDaJu
* @Date 2024/4/18 18:39
* @Version 1.0
*/
public interface GatewayVehicleService {
Result<String> topLine(String vin);
void loadDownLine(String vin);
}

View File

@ -0,0 +1,285 @@
package com.muyu.loadCenter.service.impl;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.muyu.loadCenter.aliyun.service.AliYunEcsService;
import com.muyu.loadCenter.domain.EcsInstanceInfo;
import com.muyu.loadCenter.domain.WorkGatewayNode;
import com.muyu.loadCenter.gateway.cache.*;
import com.muyu.loadCenter.gateway.model.GatewayNodeInfo;
import com.muyu.loadCenter.redis.service.RedisService;
import com.muyu.loadCenter.service.GatewayLoadService;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @ProjectName: load_center
* @PackageName: com.muyu.loadCenter.service.impl
* @Description
* @Author HuangDaJu
* @Date 2024/4/18 14:16
* @Version 1.0
*/
@Service
@Log4j2
@AllArgsConstructor
public class GatewayLoadServiceImpl implements GatewayLoadService {
private final Long nodeLength = 100L;
/**
*
*/
private final GatewayLoadNodeCache gatewayLoadNodeCache;
/**
*
* @return
*/
private final GatewayLoadSeriesCache gatewayLoadSeriesCache;
/**
*
* @return
*/
private final GatewayNodeCache gatewayNodeCache;
@Autowired
private RedisService redisService;
private final GatewayZSetNodeCache gatewayZSetNodeCache;
/**
* ECS
*/
@Autowired
private AliYunEcsService aliYunEcsService;
/**
* aa +1
*/
static int aa=0;
/**
* bb +1 >=
*/
static int bb=0;
@Override
public String loadNode() {
List<String> loadNodeList = new ArrayList<>();
ArrayList<WorkGatewayNode> nodeIdList = new ArrayList<>();
Map<Object, Double> map = gatewayZSetNodeCache.get();
for (Map.Entry<Object, Double> entry : map.entrySet()) {
WorkGatewayNode workGatewayNode1 = new WorkGatewayNode();
log.info(entry.getKey().toString()+"--"+entry.getValue());
workGatewayNode1.setNodeId(entry.getKey().toString());
workGatewayNode1.setWeight(entry.getValue().intValue());
nodeIdList.add(workGatewayNode1);
}
long count = nodeIdList.stream().mapToInt(WorkGatewayNode::getWeight).sum();
if (count < 100) {
List<WorkGatewayNode> list = nodeIdList.stream()
.sorted((o1, o2) -> o2.getWeight() - o1.getWeight())
.toList();
int countWeight = 0;
for (long i = count; i < 100; i++) {
WorkGatewayNode workGatewayNode = list.get(countWeight++ % list.size());
workGatewayNode.setWeight(workGatewayNode.getWeight() + 1);
}
}
whFor:
while (true) {
for (WorkGatewayNode workGatewayNode : nodeIdList) {
int weight = workGatewayNode.getWeight();
if (weight > 0) {
loadNodeList.add(
workGatewayNode.getNodeId()
);
workGatewayNode.setWeight(weight - 1);
}
}
int sum = nodeIdList.stream()
.mapToInt(WorkGatewayNode::getWeight)
.sum();
if (sum <= 0) {
break whFor;
}
}
gatewayLoadNodeCache.put(loadNodeList);
Long seriesLoad = gatewayLoadSeriesCache.incrementAndGet();
System.out.println("seriesLoad:" + seriesLoad);
Long seriesLoadIndex = seriesLoad % nodeLength;
String loadNodeId = gatewayLoadNodeCache.getByIndex(seriesLoadIndex);
GatewayNodeInfo gatewayNodeInfo = gatewayNodeCache.get(loadNodeId);
return gatewayNodeInfo.getPublicIdAddress();
}
@Override
public void scheduleECS() {
// 客户端初始化
OkHttpClient client = new OkHttpClient();
ArrayList<String> ipCacheSet = new ArrayList<>();
// 从Redis获取服务器IP集合
Map<Object, Double> map = gatewayZSetNodeCache.get();
for (Map.Entry<Object, Double> entry : map.entrySet()) {
ipCacheSet.add(entry.getKey().toString());
}
log.info("共有个"+ipCacheSet.size()+"服务器");
// 遍历每台服务器进行负载检查
for (String ip : ipCacheSet) {
// 构建请求URL和请求头
String URL = "http://"+ip+":8080/public/cluster";
Request request = new Request.Builder()
.url(URL)
.get()
.addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
.addHeader("Accesstoken", "")
.build();
try {
Response response = client.newCall(request).execute();
// 解析响应数据
JSONArray jsonArray = JSONArray.parseArray(response.body().string());
JSONObject jsonObject = jsonArray.getJSONObject(0);
JSONObject mqttInfo = jsonObject.getJSONObject("mqttInfo");
int connectSize = mqttInfo.getIntValue("connectSize");
log.info("服务器:"+ip+"-车辆连接数:"+connectSize);
// 更新Redis中服务器的连接数ZSet数据类型
gatewayZSetNodeCache.put(ip,connectSize);
// 根据连接数判断是否需要进行扩容或缩容
if (connectSize >= 8) {
aa++;
// 当满足扩容条件时,记录日志并执行扩容操作
if (aa == ipCacheSet.size()) {
log.info(aa+"------------------------------------------"+ipCacheSet.size());
log.info("需要扩容");
// 调用阿里云ECS服务创建新实例
String instanceId = aliYunEcsService.runInstances();
log.info("扩容的节点ip为" + instanceId);
// 休眠5秒以确保新实例创建完成
Thread.sleep(5000);
// 获取新实例信息并将其放入redis
EcsInstanceInfo ecsInstanceInfo = aliYunEcsService.selectList(instanceId);
GatewayNodeInfo gatewayNodeInfo = new GatewayNodeInfo();
gatewayNodeInfo.setNodeId(ecsInstanceInfo.getInstanceId());
gatewayNodeInfo.setPublicIdAddress(ecsInstanceInfo.getPublicIpAddress());
gatewayNodeInfo.setPrivateIdAddress(ecsInstanceInfo.getPrivateIpAddress());
gatewayNodeCache.put(ecsInstanceInfo.getPublicIpAddress(), gatewayNodeInfo);
//这里模拟(也可以在别的类里完成) ECS创建成功后服务器发送一条消息服务器正常启动mq可以正常使用存入redis
gatewayZSetNodeCache.put(ecsInstanceInfo.getPublicIpAddress(), 0);
log.info("实例id和公网ip存入redis");
aa = 0; // 重置计数器
}
}else {
aa = 0;
}
if (connectSize <= 2) {
bb++;
System.out.println("bb:"+bb);
//缩容逻辑:删除连接数过低的服务器实例,出现连续两个节点连接数低于5的则执行缩容操作
if (bb >= 2){
log.info("释放实例"+ip);
gatewayZSetNodeCache.remove(ip);
GatewayNodeInfo gatewayNodeInfo = gatewayNodeCache.get(ip);
//这里再来个异步操作 将 GatewayNodeInfo 对象传走,进行异步操作
// 1.分批次解除连接的车辆
// 2.删除各个相关的redis缓存
// aliYunEcsService.releaseECS(gatewayNodeInfo.getNodeId()); // 释放ECS实例
bb = 0;
}
}else{
bb = 0;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
// else if (connectSize <= 2) {
//删除ECS里面的ip车辆再次上线找不到这个要缩容的服务器让找不到
// redisService.deleteCacheZset("ECS" ,ip);
// 缩容逻辑:删除连接数过低的服务器实例
// String url = "http://127.0.0.1:9006/ecsInstance/select/" + ip;
// Result result = restTemplate.postForObject(url, null, Result.class);
// String instanceId = (String) result.getData();
// Long i = redisService.deleteCacheZset("ECS", ip);// 从Redis中删除该服务器的记录
// }

View File

@ -0,0 +1,82 @@
package com.muyu.loadCenter.service.impl;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.muyu.loadCenter.domain.Result;
import com.muyu.loadCenter.gateway.cache.GatewayNodeSetVinCache;
import com.muyu.loadCenter.gateway.cache.GatewayVehicleNode;
import com.muyu.loadCenter.gateway.cache.GatewayZSetNodeCache;
import com.muyu.loadCenter.service.GatewayVehicleService;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.Map;
/**
* @ProjectName: load_center
* @PackageName: com.muyu.loadCenter.service.impl
* @Description TODO
* @Author HuangDaJu
* @Date 2024/4/18 18:39
* @Version 1.0
*/
@Service
@AllArgsConstructor
@Log4j2
public class GatewayVehicleServiceImpl implements GatewayVehicleService {
private final GatewayNodeSetVinCache gatewayNodeSetVinCache;
private final GatewayZSetNodeCache gatewayZSetNodeCache;
private final GatewayVehicleNode gatewayVehicleNode;
@Autowired
private RestTemplate restTemplate;
/**
* 线
* @param vin
* @return nodeId
*/
@Override
public Result<String> topLine(String vin) {
String url="http://127.0.0.1:9010/gateway/load/node";
Result data = restTemplate.getForObject(url, Result.class);
gatewayVehicleNode.put(vin,data.getData().toString());
gatewayNodeSetVinCache.put(data.getData().toString(),vin);
return Result.success(data.getData().toString());
}
@Override
public void loadDownLine(String vin) {
String nodeId = gatewayVehicleNode.get(vin);
gatewayNodeSetVinCache.remove(nodeId,vin);
gatewayVehicleNode.remove(vin);
}
}

View File

@ -0,0 +1,30 @@
import com.muyu.loadCenter.LoadCenterApplication;
import com.muyu.loadCenter.domain.WorkGatewayNode;
import com.muyu.loadCenter.gateway.model.GatewayNodeInfo;
import com.muyu.loadCenter.redis.service.RedisService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.ArrayList;
import java.util.List;
/**
* @author DongZl
* @description:
* @Date 2024/4/12 5:13
*/
@SpringBootTest(classes = LoadCenterApplication.class)
public class LoadTest {
@Autowired
private RedisService redisService;
@Test
public void load() {
GatewayNodeInfo gatewayNodeInfo = redisService.getCacheObject("gateway:node:info:39.101.193.188");
System.out.println(gatewayNodeInfo);
}
}