feat():获取服务器信息

version-2():添加游标,通过游标+1轮询IP列表,
下一步存入节点信息
master
Saisai Liu 2024-05-31 22:15:44 +08:00
parent 0a9d3c25a8
commit abfc6d8a91
10 changed files with 284 additions and 49 deletions

View File

@ -55,6 +55,7 @@
<version>2.0.46</version> <version>2.0.46</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>

View File

@ -1,12 +1,12 @@
package com.mobai.controller; package com.mobai.controller;
import com.mobai.domain.MqttServerModel;
import com.mobai.domain.Result; import com.mobai.domain.Result;
import com.mobai.domain.VehicleConnectionReq;
import com.mobai.service.FluxGetInfoService; import com.mobai.service.FluxGetInfoService;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/** /**
* @ClassName FluxGetInfo * @ClassName FluxGetInfo
@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.RestController;
*/ */
@RestController @RestController
@Log4j2 @Log4j2
@RequestMapping("fluxmq") @RequestMapping("fluxmq/")
public class FluxGetInfoController { public class FluxGetInfoController {
@Autowired @Autowired
private FluxGetInfoService fluxGetInfoService; private FluxGetInfoService fluxGetInfoService;
@ -25,4 +25,9 @@ public class FluxGetInfoController {
public Result getInfo(){ public Result getInfo(){
return fluxGetInfoService.getInfo(null); return fluxGetInfoService.getInfo(null);
} }
@PostMapping("/getIp")
public Result vehicleConnection(@RequestBody(required = false) VehicleConnectionReq req){
return fluxGetInfoService.vehicleConnection(req);
}
} }

View File

@ -0,0 +1,93 @@
package com.mobai.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;
}

View File

@ -0,0 +1,28 @@
package com.mobai.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author DongZl
* @description: Mqtt
* @Date 2024-3-26 09:53
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MqttServerModel {
/**
* MQTT
*/
private String broker;
/**
* MQTT
*/
private String topic;
}

View File

@ -1,33 +1,30 @@
package com.mobai.domain; package com.mobai.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable; import java.io.Serializable;
/** /**
* *
* *
* @author mobai * @author ruoyi
*/ */
@Data @Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> implements Serializable { public class Result<T> implements Serializable {
/** /**
* *
*/ */
public static final int SUCCESS = Constants.SUCCESS; public static final int SUCCESS = HttpStatus.SUCCESS;
/** /**
* *
*/ */
public static final int FAIL = Constants.FAIL; public static final int FAIL = HttpStatus.ERROR;
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/**
*
*/
private static final int WARN = HttpStatus.WARN;
private int code; private int code;
private String msg; private String msg;
@ -35,11 +32,11 @@ public class Result<T> implements Serializable {
private T data; private T data;
public static <T> Result<T> success () { public static <T> Result<T> success () {
return restResult(null, SUCCESS, null); return restResult(null, SUCCESS, "操作成功");
} }
public static <T> Result<T> success (T data) { public static <T> Result<T> success (T data) {
return restResult(data, SUCCESS, null); return restResult(data, SUCCESS, "操作成功");
} }
public static <T> Result<T> success (T data, String msg) { public static <T> Result<T> success (T data, String msg) {
@ -47,7 +44,7 @@ public class Result<T> implements Serializable {
} }
public static <T> Result<T> error () { public static <T> Result<T> error () {
return restResult(null, FAIL, null); return restResult(null, FAIL, "操作失败");
} }
public static <T> Result<T> error (String msg) { public static <T> Result<T> error (String msg) {
@ -55,7 +52,7 @@ public class Result<T> implements Serializable {
} }
public static <T> Result<T> error (T data) { public static <T> Result<T> error (T data) {
return restResult(data, FAIL, null); return restResult(data, FAIL, "操作失败");
} }
public static <T> Result<T> error (T data, String msg) { public static <T> Result<T> error (T data, String msg) {
@ -66,16 +63,32 @@ public class Result<T> implements Serializable {
return restResult(null, code, 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) { public static <T> Result<T> warn (int code, String msg) {
return restResult(null, code, msg); return restResult(null, code, msg);
} }
private static <T> Result<T> restResult (T data, int code, String msg) { private static <T> Result<T> restResult (T data, int code, String msg) {
return Result.<T>builder() Result<T> apiResult = new Result<>();
.code(code) apiResult.setCode(code);
.data(data) apiResult.setData(data);
.msg(msg) apiResult.setMsg(msg);
.build(); return apiResult;
} }
public static <T> Boolean isError (Result<T> ret) { public static <T> Boolean isError (Result<T> ret) {
@ -85,5 +98,4 @@ public class Result<T> implements Serializable {
public static <T> Boolean isSuccess (Result<T> ret) { public static <T> Boolean isSuccess (Result<T> ret) {
return Result.SUCCESS == ret.getCode(); return Result.SUCCESS == ret.getCode();
} }
} }

View File

@ -0,0 +1,51 @@
package com.mobai.domain;
import com.alibaba.fastjson2.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 vin;
/**
*
*/
private String timestamp;
/**
*
*/
@JSONField(name = "username")
private String userName;
/**
*
*/
private String nonce;
}

View File

@ -7,6 +7,7 @@ import com.aliyun.ecs20140526.models.DescribeInstancesResponse;
import com.aliyun.ecs20140526.models.DescribeInstancesResponseBody; import com.aliyun.ecs20140526.models.DescribeInstancesResponseBody;
import com.aliyun.tea.TeaException; import com.aliyun.tea.TeaException;
import com.mobai.domain.ApifoxModel; import com.mobai.domain.ApifoxModel;
import com.mobai.domain.MqttServerModel;
import com.mobai.domain.Result; import com.mobai.domain.Result;
import com.mobai.service.FluxGetInfoService; import com.mobai.service.FluxGetInfoService;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@ -50,6 +51,7 @@ public class SelectInstances {
return new com.aliyun.ecs20140526.Client(config); return new com.aliyun.ecs20140526.Client(config);
} }
// @Scheduled(cron = "0 0/10 * * * ? ")
@Scheduled(cron = "0/10 * * * * ? ") @Scheduled(cron = "0/10 * * * * ? ")
public void saveIps() throws Exception { public void saveIps() throws Exception {
List<String> ips = new ArrayList<>(); List<String> ips = new ArrayList<>();
@ -126,35 +128,38 @@ public class SelectInstances {
arithmet.put(node.getIp(), value); arithmet.put(node.getIp(), value);
}// 根据权重总和计算每个节点的特定比例 }// 根据权重总和计算每个节点的特定比例
log.info("总可负载量:{}", arithmet); log.info("总可负载量:{}", arithmet);
List<String> ips = new ArrayList<>(); List<MqttServerModel> ips = new ArrayList<>();
//获取每个ip的分配率 //获取每个ip的分配率
for (String ip : arithmet.keySet()) { for (String ip : arithmet.keySet()) {
//概率 //概率
BigDecimal probability = arithmet.get(ip).divide(sum, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)); BigDecimal probability = arithmet.get(ip).divide(sum, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
arithmet.put(ip, probability); arithmet.put(ip, probability);
log.info("{}可负载率(权重值){}",ip, probability); log.info("{}可负载率(权重值){}", ip, probability);
} }
Set<String> ipSet = arithmet.keySet(); Set<String> ipSet = arithmet.keySet();
BigDecimal finalSum = sum; BigDecimal finalSum = sum;
Map<String, Integer> map = new HashMap<>(); Map<String, Integer> map = new HashMap<>();
// 转换成数量 // 转换成数量
ipSet.forEach(ip -> ipSet.forEach(ip -> map.put(ip, arithmet.get(ip).multiply(finalSum).intValue() / 100));
map.put(ip, arithmet.get(ip).multiply(finalSum).intValue() / 100)
);
Long i = 0L; Long i = 0L;
log.info("ip对应可分配车辆{}",map); log.info("ip对应可分配车辆{}", map);
int sumInit = map.values().stream().mapToInt(num -> num).sum(); int sumInit = map.values().stream().mapToInt(num -> num).sum();
while (true) { while (true) {
ipSet = map.keySet(); ipSet = map.keySet();
Iterator<String> iterator = ipSet.iterator(); Iterator<String> iterator = ipSet.iterator();
i++; i++;
while (iterator.hasNext()) { while (iterator.hasNext()) {
MqttServerModel mqttServerModel = new MqttServerModel();
String ip = iterator.next(); String ip = iterator.next();
ips.add(ip); for (SmallNode node : nodes) {
if (node.ip.equals(ip)) mqttServerModel = new MqttServerModel(ip, "topic" + nodes.indexOf(node));
}
ips.add(mqttServerModel);
int i1 = map.get(ip) - 1; int i1 = map.get(ip) - 1;
map.put(ip, i1); map.put(ip, i1);
if (map.get(ip).equals(0)) { if (i1 == 0) {
map.remove(ip); map.remove(ip);
} }
} }
@ -162,7 +167,7 @@ public class SelectInstances {
break; break;
} }
} }
redisTemplate.opsForValue().set("fluxMq", JSON.toJSONString(ips)); redisTemplate.opsForList().leftPush("fluxMq", JSON.toJSONString(ips));
// 可负载IP轮询排列 // 可负载IP轮询排列
log.info("排列ip,{}", ips); log.info("排列ip,{}", ips);
} }

View File

@ -1,6 +1,7 @@
package com.mobai.service; package com.mobai.service;
import com.mobai.domain.Result; import com.mobai.domain.Result;
import com.mobai.domain.VehicleConnectionReq;
/** /**
* @ClassName FluxGetInfoService * @ClassName FluxGetInfoService
@ -12,4 +13,8 @@ public interface FluxGetInfoService {
Result getInfo(String ip); Result getInfo(String ip);
Result vehicleConnection(VehicleConnectionReq req);
} }

View File

@ -1,26 +1,20 @@
package com.mobai.service.impl; package com.mobai.service.impl;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.mobai.domain.AcceptToken; import com.mobai.domain.*;
import com.mobai.domain.ApifoxModel;
import com.mobai.domain.Result;
import com.mobai.domain.User;
import com.mobai.service.FluxGetInfoService; import com.mobai.service.FluxGetInfoService;
import okhttp3.*; import lombok.extern.log4j.Log4j2;
import org.apache.catalina.authenticator.SpnegoAuthenticator;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity; import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* @ClassName FluxGetInfoServiceImpl * @ClassName FluxGetInfoServiceImpl
@ -28,23 +22,33 @@ import java.util.Map;
* @Author SaiSai.Liu * @Author SaiSai.Liu
* @Date 2024/5/28 22:01 * @Date 2024/5/28 22:01
*/ */
@Log4j2
@Service @Service
public class FluxGetInfoServiceImpl implements FluxGetInfoService { public class FluxGetInfoServiceImpl implements FluxGetInfoService {
@Autowired @Autowired
private RestTemplate restTemplate; private RestTemplate restTemplate;
@Autowired
private RedisTemplate<String, String> redis;
/**
* ip
*
* @param ip
* @return
*/
@Override @Override
public Result getInfo(String ip) { public Result getInfo(String ip) {
String url = null; String url = null;
if (ip==null){ if (ip == null) {
url= "http://39.98.50.223:8080/public/"; url = "http://39.98.50.223:8080/public/";
}else { } else {
url = "http://"+ip+":8080/public/"; url = "http://" + ip + ":8080/public/";
} }
User user = new User("fluxmq", "fluxmq"); User user = new User("fluxmq", "fluxmq");
//登录 //登录
AcceptToken token = restTemplate.postForObject(url+"login", user, AcceptToken.class); AcceptToken token = restTemplate.postForObject(url + "login", user, AcceptToken.class);
//请求头 //请求头
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.add("token", token.getAccessToken()); headers.add("token", token.getAccessToken());
@ -58,4 +62,33 @@ public class FluxGetInfoServiceImpl implements FluxGetInfoService {
return Result.success(apifoxModel.get(0)); return Result.success(apifoxModel.get(0));
} }
@Override
public Result vehicleConnection(VehicleConnectionReq req) {
// "vehicleVin": "VIN1234567894" vin
// "timestamp": "11111" new Date().getMillis()
// "username": "你好" Vin + timestamp
// "nonce": "33" 随机
log.warn("参数为:{}", req);
String string = redis.opsForList().range("fluxMq", 0, -1).get(0);
List<MqttServerModel> mqtts = JSON.parseArray(string, MqttServerModel.class);
log.info("集合:{}",mqtts);
if (redis.hasKey("fluxMqIndex")) {
redis.opsForValue().increment("fluxMqIndex", 1);
} else {
redis.opsForValue().set("fluxMqIndex", 0 + "");
}
int index = Integer.valueOf(redis.opsForValue().get("fluxMqIndex"));
log.info("下标:{}",index);
MqttServerModel mqttServerModel = mqtts.get(index);
if (index + 1 == redis.opsForList().size("fluxmq")) {
redis.delete("fluxMqIndex");
}
log.info("已获取到对象:{}",mqttServerModel);
return Result.success(mqttServerModel);
}
} }
// 达到60%开启新服务30%关闭低实例

View File

@ -1,3 +1,5 @@
server:
port: 8081
spring: spring:
redis: redis:
host: 43.142.100.73 host: 43.142.100.73