[Octopus] modify project to SpringBoot version
This commit is contained in:
@@ -0,0 +1,264 @@
|
||||
package io.wdd.common.handler;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import io.wdd.common.response.R;
|
||||
import io.wdd.common.response.ResultStat;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.amqp.rabbit.support.ListenerExecutionFailedException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.validation.ObjectError;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLIntegrityConstraintViolationException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 自定义 全局异常处理类
|
||||
* 全局处理响应数据的全局处理类,继承ResponseBodyAdvice接口重写其中的方法,
|
||||
* (带有@RequestMapping注解的方法上抛出的异常都会拦截),在此统一处理并统一返回数据格式
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
@Slf4j(topic = "Global Exception")
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
@Autowired
|
||||
private MyMessageSource messageSource;
|
||||
|
||||
/**
|
||||
* 全局异常拦截方法
|
||||
* 这里拦截此异常,将异常中的信息提取返回有效信息!
|
||||
*
|
||||
* @param e SpringBoot参数校验(valid)过程中,检验失败会产生此异常,在此处拦截
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public R<Object> MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
|
||||
|
||||
// 从异常对象中拿到ObjectError对象,获取所有的错误信息
|
||||
List<ObjectError> objectError = e
|
||||
.getBindingResult()
|
||||
.getAllErrors();
|
||||
|
||||
// 然后提取错误提示信息进行返回
|
||||
HashMap<Integer, String> errorMap = new HashMap<>();
|
||||
objectError.forEach(objectError1 -> errorMap.put(
|
||||
objectError.indexOf(objectError1),
|
||||
objectError1.getDefaultMessage()
|
||||
));
|
||||
|
||||
// 使用标准化返回体返回数据
|
||||
return R.resetResult(
|
||||
ResultStat.VALIDATE_FAILED.getCode(),
|
||||
ResultStat.VALIDATE_FAILED.getDescription(),
|
||||
errorMap
|
||||
);
|
||||
//return errorMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param exception 参数类型错误,拦截器
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
|
||||
public Object methodArgumentNotValidException(MethodArgumentTypeMismatchException exception) {
|
||||
//按需重新封装需要返回的错误信息
|
||||
Map<String, String> invalidMap = new LinkedHashMap(99);
|
||||
//解析原错误信息,封装后返回,此处返回非法的字段名称,原始值,错误信息
|
||||
invalidMap.put(
|
||||
exception
|
||||
.getParameter()
|
||||
.getParameterName(),
|
||||
ResultStat.PARAM_ERROR.getDescription()
|
||||
);
|
||||
R<Map<String, String>> vo = new R<>();
|
||||
|
||||
vo.setCode(ResultStat.PARAM_ERROR.getCode());
|
||||
vo.setMsg(getLocaleMsg(ResultStat.PARAM_ERROR.getDescription()));
|
||||
vo.setData(invalidMap);
|
||||
|
||||
log.debug(
|
||||
exception.getMessage(),
|
||||
exception
|
||||
);
|
||||
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理此种异常
|
||||
*
|
||||
* @param httpRequestMethodNotSupportedException
|
||||
*/
|
||||
@ExceptionHandler(value = {HttpRequestMethodNotSupportedException.class})
|
||||
public void methodNotMatchHandler(HttpRequestMethodNotSupportedException httpRequestMethodNotSupportedException) {
|
||||
|
||||
log.error(
|
||||
httpRequestMethodNotSupportedException.getMessage()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = {ListenerExecutionFailedException.class})
|
||||
public void listenerExecutionFailedExceptionHandler(ListenerExecutionFailedException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 拦截数据库异常
|
||||
*
|
||||
* @param exception 数据库异常
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = {SQLException.class, DuplicateKeyException.class})
|
||||
public R<String> sqlExceptionHandler(SQLException exception) {
|
||||
|
||||
R<String> vo = new R<>();
|
||||
|
||||
vo.setCode(ResultStat.PARAM_ERROR.getCode());
|
||||
vo.setMsg(getLocaleMsg(ResultStat.PARAM_ERROR.getDescription()));
|
||||
if (exception instanceof SQLIntegrityConstraintViolationException) {
|
||||
vo.setData("Data already exsit ! 操作失败!");
|
||||
} else {
|
||||
vo.setData("数据库异常,操作失败!");
|
||||
}
|
||||
|
||||
log.debug(
|
||||
exception.getMessage(),
|
||||
exception
|
||||
);
|
||||
|
||||
return vo;
|
||||
}
|
||||
|
||||
@ExceptionHandler(MyRuntimeException.class)
|
||||
public R<Object> interceptMyRuntimeE(MyRuntimeException exception) {
|
||||
|
||||
R<Object> R = new R<>();
|
||||
ResultStat status = exception.getStatus();
|
||||
if (status != null) {
|
||||
R.setMsg(getLocaleMsg(
|
||||
exception.getMessage(),
|
||||
exception.getParams()
|
||||
));
|
||||
R.setCode(status.getCode());
|
||||
R.setData(exception.getData());
|
||||
} else {
|
||||
R.setCode(ResultStat.FAILED.getCode());
|
||||
R.setMsg(getLocaleMsg(
|
||||
exception.getMessage(),
|
||||
exception.getParams()
|
||||
));
|
||||
R.setData(null);
|
||||
}
|
||||
return R;
|
||||
}
|
||||
// /**
|
||||
// *
|
||||
// * 统一Spring Security的认证错误
|
||||
// * */
|
||||
// @ExceptionHandler(value = BadCredentialsException.class)
|
||||
// public R<Object> badCredentialsException(BadCredentialsException exception){
|
||||
//
|
||||
// log.error(exception.getDescription());
|
||||
//
|
||||
// return R.failed(ResultStat.USER_AUTH_FAILED);
|
||||
// }
|
||||
|
||||
/**
|
||||
* validate 验证错误handle
|
||||
*/
|
||||
@ExceptionHandler(value = BindException.class)
|
||||
public Object bindExceptionHandler(BindException exception) {
|
||||
//按需重新封装需要返回的错误信息
|
||||
Map<String, String> invalidMap = Maps.newLinkedHashMap();
|
||||
|
||||
//解析原错误信息,封装后返回,此处返回非法的字段名称,原始值,错误信息
|
||||
if (exception != null) {
|
||||
List<FieldError> fieldErrors = exception
|
||||
.getBindingResult()
|
||||
.getFieldErrors();
|
||||
fieldErrors
|
||||
.stream()
|
||||
.sorted(Comparator.comparing(FieldError::getCode))
|
||||
.forEach(error -> {
|
||||
String defaultMessage = error.getDefaultMessage();
|
||||
String finalMessage = defaultMessage;
|
||||
if (defaultMessage != null && defaultMessage.startsWith("{") && defaultMessage.endsWith("}")) {
|
||||
finalMessage = messageSource.getMessage(defaultMessage.substring(
|
||||
1,
|
||||
defaultMessage.length() - 1
|
||||
));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(invalidMap.get(error.getField()))) {
|
||||
invalidMap.put(
|
||||
error.getField(),
|
||||
invalidMap.get(error.getField()) + "," + finalMessage
|
||||
);
|
||||
} else {
|
||||
invalidMap.put(
|
||||
error.getField(),
|
||||
finalMessage
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
R<Map<String, String>> vo = new R<>();
|
||||
vo.setCode(ResultStat.VALIDATE_FAILED.getCode());
|
||||
vo.setMsg(getLocaleMsg(ResultStat.VALIDATE_FAILED.getDescription()));
|
||||
vo.setData(invalidMap);
|
||||
|
||||
log.debug(
|
||||
exception.getMessage(),
|
||||
exception
|
||||
);
|
||||
|
||||
return vo;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认异常统一处理 Exception
|
||||
*/
|
||||
@ExceptionHandler(value = Exception.class)
|
||||
public Object exceptionHandel(Exception e) {
|
||||
return getResponseVO(
|
||||
e,
|
||||
getLocaleMsg("系统错误,请联系管理员")
|
||||
);
|
||||
}
|
||||
|
||||
private Object getResponseVO(Exception e, String msg) {
|
||||
R<String> R = new R<>();
|
||||
R.setCode(ResultStat.FAILED.getCode());
|
||||
R.setMsg(msg);
|
||||
R.setMsg(e.getMessage());
|
||||
|
||||
// 此处修改不要打印 错误 e
|
||||
log.error(
|
||||
e.getMessage(),
|
||||
e
|
||||
);
|
||||
return R;
|
||||
}
|
||||
|
||||
private String getLocaleMsg(String msgCode, Object... params) {
|
||||
return messageSource.getMessage(
|
||||
msgCode,
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package io.wdd.common.handler;
|
||||
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Locale;
|
||||
|
||||
@Component
|
||||
public class MyMessageSource {
|
||||
|
||||
@Resource
|
||||
private MessageSource messageSource;
|
||||
|
||||
public MyMessageSource() {
|
||||
}
|
||||
|
||||
public String getMessage(String code, Object... params) {
|
||||
return this.getMessage(code, (Object[])null, params);
|
||||
}
|
||||
|
||||
public String getMessageIgnoreMissMatch(String code, Object... params) {
|
||||
Locale locale = LocaleContextHolder.getLocale();
|
||||
String message = this.messageSource.getMessage(code, (Object[])null, code, locale);
|
||||
return this.parse(message, true, params);
|
||||
}
|
||||
|
||||
public String getMessage(String code, Object[] args, Object... params) {
|
||||
return this.getMessage(code, args, code, params);
|
||||
}
|
||||
|
||||
public String getMessage(String code, Object[] args, String defaultMessage, Object... params) {
|
||||
Locale locale = LocaleContextHolder.getLocale();
|
||||
String message = this.messageSource.getMessage(code, args, defaultMessage, locale);
|
||||
return this.parse(message, false, params);
|
||||
}
|
||||
|
||||
private String parse(String s, boolean ingoreParamsMissMath, Object... params) {
|
||||
if (s == null) {
|
||||
return null;
|
||||
} else if (params == null) {
|
||||
return s;
|
||||
} else {
|
||||
String[] splits = s.split("\\{}", -1);
|
||||
if (splits.length != params.length + 1) {
|
||||
if (ingoreParamsMissMath) {
|
||||
return s;
|
||||
} else {
|
||||
throw new IllegalArgumentException("The number of parameters is inconsistent with the parameter value");
|
||||
}
|
||||
} else if (splits.length == 1) {
|
||||
return s;
|
||||
} else {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
for(int i = 0; i < splits.length; ++i) {
|
||||
String split = splits[i];
|
||||
stringBuilder.append(split);
|
||||
if (i < params.length) {
|
||||
stringBuilder.append(params[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package io.wdd.common.handler;
|
||||
|
||||
import io.wdd.common.response.ResultStat;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MyRuntimeException extends RuntimeException {
|
||||
|
||||
private Object data;
|
||||
private ResultStat status;
|
||||
|
||||
private Object[] params;
|
||||
|
||||
public MyRuntimeException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public MyRuntimeException(String msg, Object... params) {
|
||||
super(msg);
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public MyRuntimeException(ResultStat status, Object data, String msg, Object... params) {
|
||||
super(msg == null ? status.getDescription() : msg);
|
||||
this.data = data;
|
||||
this.status = status;
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public MyRuntimeException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public MyRuntimeException(Throwable cause, String msg) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
48
server/src/main/java/io/wdd/common/response/R.java
Normal file
48
server/src/main/java/io/wdd/common/response/R.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package io.wdd.common.response;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class R<T> {
|
||||
|
||||
int code;
|
||||
|
||||
String msg;
|
||||
|
||||
T data;
|
||||
|
||||
private R(int code, String msg, T data) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public R() {
|
||||
|
||||
}
|
||||
|
||||
public static <T> R<T> ok(T data) {
|
||||
return resetResult(data, ResultStat.SUCCESS);
|
||||
}
|
||||
|
||||
public static <T> R<T> okNoData() {
|
||||
return new R();
|
||||
}
|
||||
|
||||
public static <T> R<T> failed(T data) {
|
||||
return resetResult(data, ResultStat.FAILED);
|
||||
}
|
||||
|
||||
// access from inner
|
||||
private static <T> R<T> resetResult(T data, ResultStat resultStat) {
|
||||
return new R(resultStat.getCode(), resultStat.getDescription(), data);
|
||||
}
|
||||
|
||||
// access to public
|
||||
public static <T> R<T> resetResult(int code, String msg, T data) {
|
||||
return new R<>(code
|
||||
, msg, data);
|
||||
}
|
||||
|
||||
}
|
||||
31
server/src/main/java/io/wdd/common/response/ResultStat.java
Normal file
31
server/src/main/java/io/wdd/common/response/ResultStat.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package io.wdd.common.response;
|
||||
|
||||
public enum ResultStat {
|
||||
|
||||
SUCCESS(1000, "success"),
|
||||
|
||||
FAILED(5001, "failed"),
|
||||
|
||||
VALIDATE_FAILED(1002, "参数校验失败"),
|
||||
|
||||
PARAM_ERROR(1003, "请求参数错误!"),
|
||||
|
||||
BAD(5001, "all error !");
|
||||
|
||||
int code;
|
||||
|
||||
String description;
|
||||
|
||||
ResultStat(int code, String description){
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDescription(){
|
||||
return description;
|
||||
}
|
||||
}
|
||||
64
server/src/main/java/io/wdd/common/utils/DataUnit.java
Normal file
64
server/src/main/java/io/wdd/common/utils/DataUnit.java
Normal file
@@ -0,0 +1,64 @@
|
||||
package io.wdd.common.utils;
|
||||
|
||||
import org.springframework.util.unit.DataSize;
|
||||
|
||||
/**
|
||||
* 数据单位封装<p>
|
||||
* 此类来自于:Spring-framework
|
||||
*
|
||||
* <pre>
|
||||
* BYTES 1B 2^0 1
|
||||
* KILOBYTES 1KB 2^10 1,024
|
||||
* MEGABYTES 1MB 2^20 1,048,576
|
||||
* GIGABYTES 1GB 2^30 1,073,741,824
|
||||
* TERABYTES 1TB 2^40 1,099,511,627,776
|
||||
* </pre>
|
||||
*
|
||||
* @author Sam Brannen,Stephane Nicoll
|
||||
* @since 5.3.10
|
||||
*/
|
||||
public enum DataUnit {
|
||||
|
||||
/**
|
||||
* Bytes, 后缀表示为: {@code B}.
|
||||
*/
|
||||
BYTES("B", DataSize.ofBytes(1)),
|
||||
|
||||
/**
|
||||
* Kilobytes, 后缀表示为: {@code KB}.
|
||||
*/
|
||||
KILOBYTES("KB", DataSize.ofKilobytes(1)),
|
||||
|
||||
/**
|
||||
* Megabytes, 后缀表示为: {@code MB}.
|
||||
*/
|
||||
MEGABYTES("MB", DataSize.ofMegabytes(1)),
|
||||
|
||||
/**
|
||||
* Gigabytes, 后缀表示为: {@code GB}.
|
||||
*/
|
||||
GIGABYTES("GB", DataSize.ofGigabytes(1)),
|
||||
|
||||
/**
|
||||
* Terabytes, 后缀表示为: {@code TB}.
|
||||
*/
|
||||
TERABYTES("TB", DataSize.ofTerabytes(1));
|
||||
|
||||
public static final String[] UNIT_NAMES = new String[]{"B", "KB", "MB", "GB", "TB", "PB", "EB"};
|
||||
|
||||
private final String suffix;
|
||||
|
||||
private final DataSize size;
|
||||
|
||||
|
||||
DataUnit(String suffix, DataSize size) {
|
||||
this.suffix = suffix;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
DataSize size() {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
33
server/src/main/java/io/wdd/common/utils/FormatUtils.java
Normal file
33
server/src/main/java/io/wdd/common/utils/FormatUtils.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package io.wdd.common.utils;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
public class FormatUtils {
|
||||
|
||||
|
||||
/**
|
||||
* 格式化输出百分比
|
||||
*
|
||||
* @param rate
|
||||
* @return
|
||||
*/
|
||||
public static String formatRate(double rate) {
|
||||
return new DecimalFormat("#.##%").format(rate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化输出大小 B/KB/MB...
|
||||
*
|
||||
* @param size
|
||||
* @return
|
||||
*/
|
||||
public static String formatData(long size) {
|
||||
if (size <= 0L) {
|
||||
return "0B";
|
||||
} else {
|
||||
int digitGroups = Math.min(DataUnit.UNIT_NAMES.length - 1, (int) (Math.log10((double) size) / Math.log10(1024.0D)));
|
||||
return (new DecimalFormat("#,##0.##")).format((double) size / Math.pow(1024.0D, digitGroups)) + " " + DataUnit.UNIT_NAMES[digitGroups];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
117
server/src/main/java/io/wdd/common/utils/FunctionReader.java
Normal file
117
server/src/main/java/io/wdd/common/utils/FunctionReader.java
Normal file
@@ -0,0 +1,117 @@
|
||||
package io.wdd.common.utils;
|
||||
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class FunctionReader {
|
||||
|
||||
|
||||
public static List<List<String>> ReadFileToCommandList(String functionFilePath) {
|
||||
|
||||
// https://www.digitalocean.com/community/tutorials/java-read-file-line-by-line
|
||||
|
||||
List<List<String>> result = null;
|
||||
|
||||
try {
|
||||
|
||||
BufferedReader bufferedReader = new BufferedReader(new FileReader(functionFilePath));
|
||||
result = doReadContent(
|
||||
result,
|
||||
bufferedReader
|
||||
);
|
||||
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static List<List<String>> ReadStringToCommandList(String functionContent) {
|
||||
|
||||
List<List<String>> result = null;
|
||||
|
||||
try {
|
||||
// 构造一个 buffered Reader
|
||||
BufferedReader bufferedReader = new BufferedReader(
|
||||
new StringReader(functionContent)
|
||||
);
|
||||
|
||||
// 执行read操作
|
||||
result = doReadContent(
|
||||
result,
|
||||
bufferedReader
|
||||
);
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 实际解析从前端传入的 脚本命令, 将其转换为 List<List<String>>
|
||||
*
|
||||
* @param result
|
||||
* @param bufferedReader
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
private static List<List<String>> doReadContent(List<List<String>> result, BufferedReader bufferedReader) throws IOException {
|
||||
|
||||
String line = bufferedReader.readLine();
|
||||
|
||||
if (line != null) {
|
||||
result = new ArrayList<>(64);
|
||||
}
|
||||
|
||||
while (line != null) {
|
||||
if (!StringUtils.isEmpty(line)) {
|
||||
result.add(SplitSpaceIndentToCommandList(line));
|
||||
}
|
||||
line = bufferedReader.readLine();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<String> SplitSpaceIndentToCommandList(String commandLine) {
|
||||
|
||||
return Arrays
|
||||
.stream(commandLine
|
||||
.split(" "))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static List<String> SplitCommaIndentToCommandList(String commandLine) {
|
||||
|
||||
// 需要进行归一化,去除掉多余的空格
|
||||
return Arrays
|
||||
.stream(commandLine.split(","))
|
||||
.map(
|
||||
split -> split.replace(
|
||||
" ",
|
||||
""
|
||||
)
|
||||
)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
32
server/src/main/java/io/wdd/common/utils/MessageUtils.java
Normal file
32
server/src/main/java/io/wdd/common/utils/MessageUtils.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package io.wdd.common.utils;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.wdd.common.handler.MyRuntimeException;
|
||||
import io.wdd.rpc.message.OctopusMessage;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
public class MessageUtils {
|
||||
|
||||
@Autowired
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
public static OctopusMessage convert(Message message) {
|
||||
|
||||
OctopusMessage octopusMessage;
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
try {
|
||||
octopusMessage = objectMapper.readValue(message.getBody(), OctopusMessage.class);
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new MyRuntimeException(e.getMessage());
|
||||
}
|
||||
|
||||
return octopusMessage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package io.wdd.common.utils;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
|
||||
@Configuration
|
||||
public class OctopusObjectMapperConfig {
|
||||
|
||||
public static Jackson2ObjectMapperBuilderCustomizer common() {
|
||||
|
||||
return jacksonObjectMapperBuilder -> {
|
||||
//若POJO对象的属性值为null,序列化时不进行显示
|
||||
jacksonObjectMapperBuilder.serializationInclusion(JsonInclude.Include.NON_NULL);
|
||||
|
||||
//针对于Date类型,文本格式化
|
||||
jacksonObjectMapperBuilder.simpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
//
|
||||
jacksonObjectMapperBuilder.failOnEmptyBeans(false);
|
||||
jacksonObjectMapperBuilder.failOnUnknownProperties(false);
|
||||
jacksonObjectMapperBuilder.autoDetectFields(true);
|
||||
|
||||
//针对于JDK新时间类。序列化时带有T的问题,自定义格式化字符串
|
||||
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
|
||||
jacksonObjectMapperBuilder.modules(javaTimeModule);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package io.wdd.common.utils;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
import org.springframework.amqp.core.AmqpTemplate;
|
||||
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
@Deprecated
|
||||
public class OctopusRabbitTemplateConfig {
|
||||
|
||||
@Resource
|
||||
RabbitTemplate rabbitTemplate;
|
||||
|
||||
@Bean
|
||||
public MessageConverter octopusMessageConverter() {
|
||||
JsonMapper jsonMapper = new JsonMapper();
|
||||
jsonMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
|
||||
|
||||
return new Jackson2JsonMessageConverter(jsonMapper,
|
||||
"io.wdd.common.beans.rabbitmq");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AmqpTemplate OctopusRabbitTemplate(ConnectionFactory connectionFactory) {
|
||||
|
||||
rabbitTemplate.setMessageConverter(octopusMessageConverter());
|
||||
return rabbitTemplate;
|
||||
}
|
||||
}
|
||||
231
server/src/main/java/io/wdd/common/utils/TimeUtils.java
Normal file
231
server/src/main/java/io/wdd/common/utils/TimeUtils.java
Normal file
@@ -0,0 +1,231 @@
|
||||
package io.wdd.common.utils;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class TimeUtils {
|
||||
|
||||
private static final ZoneId SYSTEM_TIME_ZONE_ID = ZoneId.of("UTC+8");
|
||||
|
||||
|
||||
/**
|
||||
* https://memorynotfound.com/calculate-relative-time-time-ago-java/
|
||||
* <p>
|
||||
* calculate relative time from now on
|
||||
* like 5 days, 3 hours, 16 minutes level 3
|
||||
*/
|
||||
|
||||
private static final Map<String, Long> times = new LinkedHashMap<>();
|
||||
|
||||
private static final String FULL_SPLIT_TIME_FORMAT = "yyyy-MM-dd-HH-mm-ss";
|
||||
private static final String COMMON_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
|
||||
/**
|
||||
* 在五秒误差内的一个统一时间
|
||||
*/
|
||||
private static LocalDateTime UNIFORM_TIME;
|
||||
|
||||
static {
|
||||
times.put(
|
||||
"year",
|
||||
TimeUnit.DAYS.toMillis(365)
|
||||
);
|
||||
times.put(
|
||||
"month",
|
||||
TimeUnit.DAYS.toMillis(30)
|
||||
);
|
||||
times.put(
|
||||
"week",
|
||||
TimeUnit.DAYS.toMillis(7)
|
||||
);
|
||||
times.put(
|
||||
"day",
|
||||
TimeUnit.DAYS.toMillis(1)
|
||||
);
|
||||
times.put(
|
||||
"hour",
|
||||
TimeUnit.HOURS.toMillis(1)
|
||||
);
|
||||
times.put(
|
||||
"minute",
|
||||
TimeUnit.MINUTES.toMillis(1)
|
||||
);
|
||||
times.put(
|
||||
"second",
|
||||
TimeUnit.SECONDS.toMillis(1)
|
||||
);
|
||||
}
|
||||
|
||||
public static ByteBuffer currentTimeByteBuffer() {
|
||||
|
||||
byte[] timeBytes = LocalDateTime
|
||||
.now(SYSTEM_TIME_ZONE_ID)
|
||||
.format(DateTimeFormatter.ofPattern(COMMON_TIME_FORMAT))
|
||||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
return ByteBuffer.wrap(timeBytes);
|
||||
}
|
||||
|
||||
public static LocalDateTime currentTime() {
|
||||
|
||||
return LocalDateTime.now(SYSTEM_TIME_ZONE_ID);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return 获取五秒时间误差内的统一时间
|
||||
*/
|
||||
public static String UniformFormatTimeString() {
|
||||
|
||||
if (ObjectUtils.isEmpty(UNIFORM_TIME)) {
|
||||
UNIFORM_TIME = currentTime();
|
||||
return currentFormatTimeString();
|
||||
}
|
||||
|
||||
// 旧的时间和新时间之家误差小于5秒,那么使用同一个时间
|
||||
if (UNIFORM_TIME
|
||||
.plusSeconds(5)
|
||||
.isAfter(currentTime())) {
|
||||
UNIFORM_TIME = currentTime();
|
||||
}
|
||||
|
||||
return localDateTimeFormatString(UNIFORM_TIME);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 格式化 去掉时间中的毫秒数
|
||||
*/
|
||||
public static LocalDateTime currentFormatTime() {
|
||||
|
||||
DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern(COMMON_TIME_FORMAT);
|
||||
|
||||
String format = LocalDateTime
|
||||
.now(SYSTEM_TIME_ZONE_ID)
|
||||
.format(ofPattern);
|
||||
|
||||
return LocalDateTime.parse(format, ofPattern);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return UTC+8 [ yyyy-MM-dd-HH-mm-ss ] Time String
|
||||
*/
|
||||
public static String currentFormatTimeString() {
|
||||
|
||||
return currentFormatTime()
|
||||
.format(DateTimeFormatter.ofPattern(FULL_SPLIT_TIME_FORMAT));
|
||||
}
|
||||
|
||||
public static LocalDateTime cvFromDate(Date date) {
|
||||
|
||||
// fix bug
|
||||
if (null == date) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return LocalDateTime.ofInstant(date.toInstant(),
|
||||
SYSTEM_TIME_ZONE_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UTC+8 [ yyyy-MM-dd HH:mm:ss ] Time String
|
||||
*/
|
||||
public static String currentTimeString() {
|
||||
|
||||
return LocalDateTime
|
||||
.now(SYSTEM_TIME_ZONE_ID)
|
||||
.format(DateTimeFormatter.ofPattern(COMMON_TIME_FORMAT));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UTC+8 [ yyyy-MM-dd-HH-mm-ss ] Time String
|
||||
*/
|
||||
public static String currentTimeStringFullSplit() {
|
||||
|
||||
return LocalDateTime
|
||||
.now(SYSTEM_TIME_ZONE_ID)
|
||||
.format(DateTimeFormatter.ofPattern(FULL_SPLIT_TIME_FORMAT));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 输出格式为 COMMON_TIME_FORMAT "yyyy-MM-dd HH:mm:ss"
|
||||
*
|
||||
* @param time
|
||||
* @return
|
||||
*/
|
||||
public static String localDateTimeString(LocalDateTime time) {
|
||||
return time.format(DateTimeFormatter.ofPattern(COMMON_TIME_FORMAT));
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出格式为 FULL_SPLIT_TIME_FORMAT "yyyy-MM-dd-HH-mm-ss"
|
||||
*
|
||||
* @param time
|
||||
* @return
|
||||
*/
|
||||
public static String localDateTimeFormatString(LocalDateTime time) {
|
||||
return time.format(DateTimeFormatter.ofPattern(FULL_SPLIT_TIME_FORMAT));
|
||||
}
|
||||
|
||||
public static String toRelative(long duration, int maxLevel) {
|
||||
StringBuilder res = new StringBuilder();
|
||||
int level = 0;
|
||||
for (Map.Entry<String, Long> time : times.entrySet()) {
|
||||
long timeDelta = duration / time.getValue();
|
||||
if (timeDelta > 0) {
|
||||
res
|
||||
.append(timeDelta)
|
||||
.append(" ")
|
||||
.append(time.getKey())
|
||||
.append(timeDelta > 1 ? "s" : "")
|
||||
.append(", ");
|
||||
duration -= time.getValue() * timeDelta;
|
||||
level++;
|
||||
}
|
||||
if (level == maxLevel) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ("".equals(res.toString())) {
|
||||
return "0 seconds ago";
|
||||
} else {
|
||||
res.setLength(res.length() - 2);
|
||||
res.append(" ago");
|
||||
return res.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static String toRelative(long duration) {
|
||||
return toRelative(
|
||||
duration,
|
||||
times.size()
|
||||
);
|
||||
}
|
||||
|
||||
public static String toRelative(Date start, Date end) {
|
||||
assert start.after(end);
|
||||
return toRelative(end.getTime() - start.getTime());
|
||||
}
|
||||
|
||||
public static String toRelative(Date start, Date end, int level) {
|
||||
assert start.after(end);
|
||||
return toRelative(
|
||||
end.getTime() - start.getTime(),
|
||||
level
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import com.amazonaws.services.s3.model.S3Object;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import io.wdd.common.beans.response.R;
|
||||
import io.wdd.common.response.R;
|
||||
import io.wdd.func.oss.config.OctopusObjectSummary;
|
||||
import io.wdd.func.oss.config.OssConfig;
|
||||
import io.wdd.func.oss.service.OSSCoreService;
|
||||
|
||||
@@ -4,7 +4,7 @@ package io.wdd.func.controller;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import io.wdd.common.beans.response.R;
|
||||
import io.wdd.common.response.R;
|
||||
import io.wdd.func.xray.beans.node.ProxyNode;
|
||||
import io.wdd.func.xray.beans.node.XrayConfigInfo;
|
||||
import io.wdd.func.xray.service.XrayCallAgent;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package io.wdd.rpc.agent;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public class AgentOperationMessage {
|
||||
|
||||
/**
|
||||
* 执行Agent Operation操作的类型
|
||||
*/
|
||||
private AgentOperationType opType;
|
||||
|
||||
/**
|
||||
* 需要执行的目标时间,
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime operationTime;
|
||||
|
||||
|
||||
/**
|
||||
* 期望升级到的目标版本
|
||||
*/
|
||||
private String updateVersion;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package io.wdd.rpc.agent;
|
||||
|
||||
public enum AgentOperationType {
|
||||
|
||||
// 上报版本信息
|
||||
VERSION,
|
||||
|
||||
// 上报核心信息
|
||||
INFO,
|
||||
|
||||
REBOOT,
|
||||
|
||||
UPDATE,
|
||||
|
||||
//关键操作,关闭Agent 只能通过此种方式完成
|
||||
SHUTDOWN
|
||||
|
||||
}
|
||||
@@ -3,11 +3,9 @@ package io.wdd.rpc.agent;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.wdd.common.beans.agent.AgentOperationMessage;
|
||||
import io.wdd.common.beans.agent.AgentOperationType;
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessage;
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessageType;
|
||||
import io.wdd.common.utils.TimeUtils;
|
||||
import io.wdd.rpc.message.OctopusMessage;
|
||||
import io.wdd.rpc.message.OctopusMessageType;
|
||||
import io.wdd.rpc.message.handler.AsyncWaitOMResult;
|
||||
import io.wdd.rpc.message.handler.OMReplayContend;
|
||||
import io.wdd.rpc.message.sender.OMessageToAgentSender;
|
||||
|
||||
@@ -2,7 +2,7 @@ package io.wdd.rpc.controller;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.wdd.common.beans.response.R;
|
||||
import io.wdd.common.response.R;
|
||||
import io.wdd.rpc.agent.OctopusAgentService;
|
||||
import io.wdd.server.beans.vo.ServerInfoVO;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
@@ -3,7 +3,7 @@ package io.wdd.rpc.controller;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import io.wdd.common.beans.response.R;
|
||||
import io.wdd.common.response.R;
|
||||
import io.wdd.rpc.execute.result.BuildStreamReader;
|
||||
import io.wdd.rpc.execute.service.AsyncExecutionService;
|
||||
import io.wdd.rpc.execute.service.SyncExecutionService;
|
||||
|
||||
@@ -4,7 +4,7 @@ package io.wdd.rpc.controller;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import io.wdd.common.beans.response.R;
|
||||
import io.wdd.common.response.R;
|
||||
import io.wdd.rpc.scheduler.beans.ScriptSchedulerVO;
|
||||
import io.wdd.rpc.scheduler.service.QuartzSchedulerService;
|
||||
import org.quartz.JobDetail;
|
||||
|
||||
@@ -3,7 +3,7 @@ package io.wdd.rpc.controller;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.wdd.common.beans.response.R;
|
||||
import io.wdd.common.response.R;
|
||||
import io.wdd.rpc.init.ServerCacheAgentStatus;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package io.wdd.rpc.execute;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.wdd.common.utils.TimeUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public class ExecutionMessage {
|
||||
|
||||
/**
|
||||
* 2023年2月22日
|
||||
* 是否需要返回 命令行的处理调用结果
|
||||
* 通过 MQ返回
|
||||
*/
|
||||
@JsonProperty(defaultValue = "false")
|
||||
boolean needResultReplay;
|
||||
|
||||
/**
|
||||
* 2023年2月22日
|
||||
* 是否是长时间持续执行任务
|
||||
*/
|
||||
@JsonProperty(defaultValue = "false")
|
||||
boolean durationTask;
|
||||
|
||||
/**
|
||||
* 用于区分 ExecutionMessage的类型
|
||||
* 直接执行预定函数,则为 Nacos配置中的 方法名称,例如 AgentUpdate AgentReboot
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 只有一行的命令行
|
||||
*/
|
||||
private List<String> singleLineCommand;
|
||||
/**
|
||||
* add in 2023-1-17
|
||||
* 页面定时脚本任务 需要传递完整的命令列表
|
||||
*/
|
||||
private List<List<String>> multiLineCommand;
|
||||
|
||||
/**
|
||||
* 词条执行命令的返回结果在Redis中的ResultKey
|
||||
*/
|
||||
private String resultKey;
|
||||
|
||||
/**
|
||||
* 生成 Command结果的 resultKey
|
||||
*
|
||||
* @param topicName
|
||||
* @return
|
||||
*/
|
||||
public static String GetResultKey(String topicName) {
|
||||
return topicName + "-Execution:" + TimeUtils.currentTimeStringFullSplit();
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟执行任务,执行的Key为未来的,生成这个和Key
|
||||
*
|
||||
* @param topicName
|
||||
* @param futureExecutionTime
|
||||
* @return
|
||||
*/
|
||||
public static String GetFutureResultKey(String topicName, LocalDateTime futureExecutionTime) {
|
||||
return topicName + "-Execution:" + TimeUtils.localDateTimeString(futureExecutionTime);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.wdd.rpc.execute.service;
|
||||
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessage;
|
||||
import io.wdd.rpc.message.OctopusMessage;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@@ -2,11 +2,11 @@ package io.wdd.rpc.execute.service;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.wdd.common.beans.executor.ExecutionMessage;
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessage;
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessageType;
|
||||
import io.wdd.common.utils.TimeUtils;
|
||||
import io.wdd.rpc.execute.ExecutionMessage;
|
||||
import io.wdd.rpc.execute.config.ExecutionLog;
|
||||
import io.wdd.rpc.message.OctopusMessage;
|
||||
import io.wdd.rpc.message.OctopusMessageType;
|
||||
import io.wdd.rpc.message.sender.OMessageToAgentSender;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@@ -9,7 +9,6 @@ import io.wdd.server.service.ExecutionLogService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.wdd.rpc.execute.service;
|
||||
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessage;
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessageType;
|
||||
import io.wdd.rpc.message.OctopusMessage;
|
||||
import io.wdd.rpc.message.OctopusMessageType;
|
||||
import io.wdd.rpc.message.handler.AsyncWaitOMResult;
|
||||
import io.wdd.rpc.message.handler.OMReplayContend;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@@ -3,11 +3,11 @@ package io.wdd.rpc.init;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.rabbitmq.client.Channel;
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessage;
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessageType;
|
||||
import io.wdd.common.beans.status.AgentStatus;
|
||||
import io.wdd.common.handler.MyRuntimeException;
|
||||
import io.wdd.rpc.message.OctopusMessage;
|
||||
import io.wdd.rpc.message.OctopusMessageType;
|
||||
import io.wdd.rpc.message.sender.OMessageToAgentSender;
|
||||
import io.wdd.rpc.status.AgentStatus;
|
||||
import io.wdd.server.beans.vo.ServerInfoVO;
|
||||
import io.wdd.server.utils.DaemonDatabaseOperator;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package io.wdd.rpc.init;
|
||||
|
||||
|
||||
import io.wdd.common.beans.status.AgentHealthyStatusEnum;
|
||||
import io.wdd.common.utils.TimeUtils;
|
||||
import io.wdd.rpc.status.AgentHealthyStatusEnum;
|
||||
import io.wdd.server.beans.vo.ServerInfoVO;
|
||||
import io.wdd.server.coreService.CoreServerService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -15,7 +15,8 @@ import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static io.wdd.common.beans.status.OctopusStatusMessage.ALL_AGENT_STATUS_REDIS_KEY;
|
||||
import static io.wdd.rpc.status.OctopusStatusMessage.ALL_AGENT_STATUS_REDIS_KEY;
|
||||
|
||||
|
||||
/**
|
||||
* Server启动或者运行的时候,需要初 缓存一系列的信息
|
||||
|
||||
40
server/src/main/java/io/wdd/rpc/message/OctopusMessage.java
Normal file
40
server/src/main/java/io/wdd/rpc/message/OctopusMessage.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package io.wdd.rpc.message;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public class OctopusMessage {
|
||||
|
||||
String uuid;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
LocalDateTime init_time;
|
||||
|
||||
/**
|
||||
* 执行操作的类型
|
||||
*/
|
||||
OctopusMessageType type;
|
||||
|
||||
// server send message content
|
||||
Object content;
|
||||
|
||||
// agent reply message content
|
||||
Object result;
|
||||
|
||||
/**
|
||||
* Agent 完成操作的时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
LocalDateTime ac_time;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package io.wdd.rpc.message;
|
||||
|
||||
public enum OctopusMessageType {
|
||||
|
||||
// agent initialization
|
||||
INIT,
|
||||
|
||||
// important things agent should do with itself
|
||||
AGENT,
|
||||
|
||||
// common shell or order execution
|
||||
EXECUTOR,
|
||||
|
||||
// update or report agent status
|
||||
STATUS
|
||||
|
||||
//
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.wdd.rpc.message.handler;
|
||||
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessage;
|
||||
import io.wdd.rpc.message.OctopusMessage;
|
||||
import io.wdd.server.config.ServerCommonPool;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -3,8 +3,8 @@ package io.wdd.rpc.message.handler;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessage;
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessageType;
|
||||
import io.wdd.rpc.message.OctopusMessage;
|
||||
import io.wdd.rpc.message.OctopusMessageType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@@ -2,8 +2,8 @@ package io.wdd.rpc.message.handler;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessage;
|
||||
import io.wdd.common.handler.MyRuntimeException;
|
||||
import io.wdd.rpc.message.OctopusMessage;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
|
||||
|
||||
@@ -2,10 +2,10 @@ package io.wdd.rpc.message.sender;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessage;
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessageType;
|
||||
import io.wdd.common.handler.MyRuntimeException;
|
||||
import io.wdd.rpc.init.InitRabbitMQConfig;
|
||||
import io.wdd.rpc.message.OctopusMessage;
|
||||
import io.wdd.rpc.message.OctopusMessageType;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
|
||||
@@ -6,7 +6,6 @@ import io.wdd.server.utils.SpringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.wdd.rpc.scheduler.config;
|
||||
|
||||
import io.wdd.common.beans.executor.ExecutionMessage;
|
||||
import io.wdd.common.utils.TimeUtils;
|
||||
import io.wdd.rpc.execute.ExecutionMessage;
|
||||
import io.wdd.rpc.scheduler.beans.ScriptSchedulerDTO;
|
||||
import org.quartz.Scheduler;
|
||||
import org.quartz.SchedulerException;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.wdd.rpc.scheduler.service.status;
|
||||
|
||||
|
||||
import io.wdd.common.beans.status.OctopusStatusMessage;
|
||||
import io.wdd.rpc.status.OctopusStatusMessage;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@@ -10,8 +10,8 @@ import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static io.wdd.common.beans.status.OctopusStatusMessage.METRIC_STATUS_MESSAGE_TYPE;
|
||||
import static io.wdd.rpc.init.ServerCacheAgentStatus.ALL_HEALTHY_AGENT_TOPIC_NAME_LIST;
|
||||
import static io.wdd.rpc.status.OctopusStatusMessage.METRIC_STATUS_MESSAGE_TYPE;
|
||||
|
||||
/**
|
||||
* 收集OctopusAgent的运行Metric信息
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.wdd.common.beans.status.AgentStatus;
|
||||
import io.wdd.rpc.status.AgentStatus;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@@ -2,11 +2,11 @@ package io.wdd.rpc.scheduler.service.status;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessage;
|
||||
import io.wdd.common.beans.rabbitmq.OctopusMessageType;
|
||||
import io.wdd.common.beans.status.OctopusStatusMessage;
|
||||
import io.wdd.common.utils.TimeUtils;
|
||||
import io.wdd.rpc.message.OctopusMessage;
|
||||
import io.wdd.rpc.message.OctopusMessageType;
|
||||
import io.wdd.rpc.message.sender.OMessageToAgentSender;
|
||||
import io.wdd.rpc.status.OctopusStatusMessage;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package io.wdd.rpc.scheduler.service.status;
|
||||
|
||||
import io.wdd.common.beans.status.OctopusStatusMessage;
|
||||
import io.wdd.common.utils.TimeUtils;
|
||||
import io.wdd.rpc.init.ServerCacheAgentStatus;
|
||||
import io.wdd.rpc.scheduler.service.BuildStatusScheduleTask;
|
||||
import io.wdd.rpc.status.OctopusStatusMessage;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
@@ -16,9 +16,9 @@ import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static io.wdd.common.beans.status.OctopusStatusMessage.ALL_AGENT_STATUS_REDIS_KEY;
|
||||
import static io.wdd.common.beans.status.OctopusStatusMessage.HEALTHY_STATUS_MESSAGE_TYPE;
|
||||
import static io.wdd.rpc.init.ServerCacheAgentStatus.ALL_AGENT_TOPIC_NAME_LIST;
|
||||
import static io.wdd.rpc.status.OctopusStatusMessage.ALL_AGENT_STATUS_REDIS_KEY;
|
||||
import static io.wdd.rpc.status.OctopusStatusMessage.HEALTHY_STATUS_MESSAGE_TYPE;
|
||||
|
||||
/**
|
||||
* 更新频率被类 BuildStatusScheduleTask.class控制
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package io.wdd.rpc.status;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* AgentHealthy状态描述实体类
|
||||
* Agent存货状态描述
|
||||
*/
|
||||
@Getter
|
||||
public enum AgentHealthyStatusEnum {
|
||||
|
||||
FAILED("FAILED", "Agent存活状态为 失败"),
|
||||
|
||||
HEALTHY("HEALTHY", "Agent存活状态为 存活"),
|
||||
|
||||
UNKNOWN("UNKNOWN", "Agent存活状态 未知");
|
||||
|
||||
String status;
|
||||
|
||||
String description;
|
||||
|
||||
|
||||
AgentHealthyStatusEnum(String status, String description) {
|
||||
this.description = description;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
41
server/src/main/java/io/wdd/rpc/status/AgentStatus.java
Normal file
41
server/src/main/java/io/wdd/rpc/status/AgentStatus.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package io.wdd.rpc.status;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public class AgentStatus {
|
||||
|
||||
private static final String AGENT_STATUS_KEY_SUFFIX = "-Status";
|
||||
|
||||
public static String getRedisStatusKey(String agentTopicName) {
|
||||
return agentTopicName+AGENT_STATUS_KEY_SUFFIX;
|
||||
}
|
||||
|
||||
String time;
|
||||
|
||||
String agentName;
|
||||
|
||||
String agentTopicName;
|
||||
|
||||
CpuInfo cpuInfo;
|
||||
|
||||
MemoryInfo memoryInfo;
|
||||
|
||||
List<DiskInfo> diskStoreInfo;
|
||||
|
||||
List<NetworkInfo> networkInfo;
|
||||
|
||||
AgentSystemInfo osInfo;
|
||||
|
||||
AppStatusInfo appStatus;
|
||||
|
||||
}
|
||||
48
server/src/main/java/io/wdd/rpc/status/AgentSystemInfo.java
Normal file
48
server/src/main/java/io/wdd/rpc/status/AgentSystemInfo.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package io.wdd.rpc.status;
|
||||
|
||||
import io.wdd.common.utils.TimeUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import oshi.software.os.OperatingSystem;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public class AgentSystemInfo {
|
||||
|
||||
String osInfo;
|
||||
|
||||
String family;
|
||||
|
||||
String manufacturer;
|
||||
|
||||
String bootTime;
|
||||
|
||||
String upTime;
|
||||
|
||||
public static AgentSystemInfo mapFromOHSISystem(OperatingSystem os) {
|
||||
|
||||
return AgentSystemInfo.builder()
|
||||
.osInfo(String.valueOf(os.getVersionInfo()))
|
||||
.family(os.getFamily())
|
||||
.manufacturer(os.getManufacturer())
|
||||
.bootTime(TimeUtils.localDateTimeString(
|
||||
LocalDateTime.ofInstant(
|
||||
Instant.ofEpochSecond(os.getSystemBootTime()),
|
||||
ZoneId.of("UTC+8")
|
||||
)
|
||||
))
|
||||
.upTime(TimeUtils.toRelative(os.getSystemUptime()*1000, 3))
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
28
server/src/main/java/io/wdd/rpc/status/AppStatusEnum.java
Normal file
28
server/src/main/java/io/wdd/rpc/status/AppStatusEnum.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package io.wdd.rpc.status;
|
||||
|
||||
public enum AppStatusEnum {
|
||||
|
||||
HEALTHY("Healthy", "app is running"),
|
||||
|
||||
FAILURE("Failure", "app is failed"),
|
||||
|
||||
NOT_INSTALL("NotInstall", "app not installed");
|
||||
|
||||
String name;
|
||||
|
||||
String description;
|
||||
|
||||
AppStatusEnum(String name, String description) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
}
|
||||
22
server/src/main/java/io/wdd/rpc/status/AppStatusInfo.java
Normal file
22
server/src/main/java/io/wdd/rpc/status/AppStatusInfo.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package io.wdd.rpc.status;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public class AppStatusInfo {
|
||||
|
||||
Set<String> Healthy;
|
||||
|
||||
Set<String> Failure;
|
||||
|
||||
Set<String> NotInstall;
|
||||
|
||||
}
|
||||
192
server/src/main/java/io/wdd/rpc/status/CpuInfo.java
Normal file
192
server/src/main/java/io/wdd/rpc/status/CpuInfo.java
Normal file
@@ -0,0 +1,192 @@
|
||||
package io.wdd.rpc.status;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import oshi.hardware.CentralProcessor;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class CpuInfo {
|
||||
|
||||
|
||||
private static final DecimalFormat LOAD_FORMAT = new DecimalFormat("#.00");
|
||||
private static final double GHZ_UNIT = 1000000000d;
|
||||
|
||||
/**
|
||||
* CPU总线程
|
||||
*/
|
||||
private Integer cpuTotal;
|
||||
|
||||
/**
|
||||
* CPU核心数
|
||||
*/
|
||||
private Integer coreTotal;
|
||||
|
||||
/**
|
||||
* CPU总数 计算方式理论上为 cpuTotal * 100
|
||||
*/
|
||||
private double cpuUsageTotol;
|
||||
|
||||
/**
|
||||
* CPU系统使用率
|
||||
*/
|
||||
private double systemCpuUsage;
|
||||
|
||||
/**
|
||||
* CPU用户使用率
|
||||
*/
|
||||
private double userCpuUsage;
|
||||
|
||||
/**
|
||||
* CPU当前等待率
|
||||
*/
|
||||
private double wait;
|
||||
|
||||
/**
|
||||
* CPU当前空闲率
|
||||
*/
|
||||
private double free;
|
||||
|
||||
/**
|
||||
* CPU型号信息
|
||||
*/
|
||||
private CpuModel cpuModel;
|
||||
|
||||
private double maxFreq;
|
||||
|
||||
private double[] runFreq;
|
||||
|
||||
private double[] cpuLoadAverage;
|
||||
|
||||
private double[] systemLoadAverage;
|
||||
|
||||
public CpuInfo(CentralProcessor processor, long waitingTime) {
|
||||
this.init(processor, waitingTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取每个CPU核心的tick,计算方式为 100 * tick / totalCpu
|
||||
*
|
||||
* @param tick tick
|
||||
* @param totalCpu CPU总数
|
||||
* @return 平均每个CPU核心的tick
|
||||
* @since 5.7.12
|
||||
*/
|
||||
private static double formatDouble(long tick, long totalCpu) {
|
||||
if (0 == totalCpu) {
|
||||
return 0D;
|
||||
}
|
||||
return Double.parseDouble(LOAD_FORMAT.format(tick <= 0 ? 0 : (100d * tick / totalCpu)));
|
||||
}
|
||||
|
||||
private static double formatDouble(double doubleNum) {
|
||||
|
||||
return Double.parseDouble(LOAD_FORMAT.format(doubleNum));
|
||||
}
|
||||
|
||||
private static double[] formatCpuLoadAverage(double[] cpuLoadAverage) {
|
||||
double[] result = new double[cpuLoadAverage.length];
|
||||
|
||||
for (int i = 0; i < cpuLoadAverage.length; i++) {
|
||||
result[i] = formatDouble(cpuLoadAverage[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static double formatCpuFrequency(long freq){
|
||||
|
||||
return Double.parseDouble(LOAD_FORMAT.format(freq / GHZ_UNIT));
|
||||
}
|
||||
|
||||
private static double[] formatCpuFrequencyList(long[] freqList){
|
||||
|
||||
int length = freqList.length;
|
||||
double[] result = new double[length];
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
result[i] = formatCpuFrequency(freqList[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定等待时间内系统CPU 系统使用率、用户使用率、利用率等等 相关信息
|
||||
*
|
||||
* @param processor {@link CentralProcessor}
|
||||
* @param waitingTime 设置等待时间,单位毫秒
|
||||
* @since 5.7.12
|
||||
*/
|
||||
private void init(CentralProcessor processor, long waitingTime) {
|
||||
|
||||
final CpuTicks ticks = new CpuTicks(processor, waitingTime);
|
||||
//this.ticks = ticks;
|
||||
|
||||
// base core info
|
||||
this.cpuTotal = processor.getLogicalProcessorCount();
|
||||
this.coreTotal = processor.getPhysicalProcessorCount();
|
||||
|
||||
// cpu information
|
||||
this.cpuModel = mapFromProcessorIdentifier(processor.getProcessorIdentifier());
|
||||
|
||||
final long totalCpu = ticks.totalCpu();
|
||||
this.cpuUsageTotol = totalCpu;
|
||||
|
||||
// cpu frequency
|
||||
this.maxFreq = formatCpuFrequency(processor.getMaxFreq());
|
||||
this.runFreq = formatCpuFrequencyList(processor.getCurrentFreq());
|
||||
|
||||
// cpu usage
|
||||
this.systemCpuUsage = formatDouble(ticks.cSys, totalCpu);
|
||||
this.userCpuUsage = formatDouble(ticks.user, totalCpu);
|
||||
this.wait = formatDouble(ticks.ioWait, totalCpu);
|
||||
this.free = formatDouble(ticks.idle, totalCpu);
|
||||
|
||||
// system load average
|
||||
this.systemLoadAverage = processor.getSystemLoadAverage(3);
|
||||
|
||||
// cpu load average
|
||||
this.cpuLoadAverage = formatCpuLoadAverage(processor.getProcessorCpuLoad(waitingTime));
|
||||
|
||||
}
|
||||
|
||||
private CpuModel mapFromProcessorIdentifier(CentralProcessor.ProcessorIdentifier id) {
|
||||
|
||||
return CpuModel.builder()
|
||||
.cpu64bit(id.isCpu64bit())
|
||||
.name(id.getName())
|
||||
.identifier(id.getIdentifier())
|
||||
.microArch(id.getMicroarchitecture())
|
||||
.vendor(id.getVendor())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* CPU型号信息
|
||||
*/
|
||||
//private CpuTicks ticks;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
private static class CpuModel {
|
||||
String name;
|
||||
|
||||
String vendor;
|
||||
|
||||
String microArch;
|
||||
|
||||
boolean cpu64bit;
|
||||
|
||||
String identifier;
|
||||
}
|
||||
|
||||
}
|
||||
99
server/src/main/java/io/wdd/rpc/status/CpuTicks.java
Normal file
99
server/src/main/java/io/wdd/rpc/status/CpuTicks.java
Normal file
@@ -0,0 +1,99 @@
|
||||
package io.wdd.rpc.status;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import oshi.hardware.CentralProcessor;
|
||||
import oshi.util.Util;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CpuTicks {
|
||||
|
||||
long idle;
|
||||
|
||||
long nice;
|
||||
|
||||
long irq;
|
||||
|
||||
long softIrq;
|
||||
|
||||
long steal;
|
||||
|
||||
long cSys;
|
||||
|
||||
long user;
|
||||
|
||||
long ioWait;
|
||||
|
||||
private static int IDLEIndex;
|
||||
private static int NICEIndex;
|
||||
private static int IRQIndex;
|
||||
private static int SOFTIRQIndex;
|
||||
private static int STEALIndex;
|
||||
private static int SYSTEMIndex;
|
||||
private static int USERIndex;
|
||||
private static int IOWAITIndex;
|
||||
|
||||
static {
|
||||
|
||||
IDLEIndex = CentralProcessor.TickType.IDLE.getIndex();
|
||||
NICEIndex = CentralProcessor.TickType.NICE.getIndex();
|
||||
IRQIndex =CentralProcessor.TickType.IRQ.getIndex();
|
||||
SOFTIRQIndex = CentralProcessor.TickType.SOFTIRQ.getIndex();
|
||||
STEALIndex = CentralProcessor.TickType.STEAL.getIndex();
|
||||
SYSTEMIndex = CentralProcessor.TickType.SYSTEM.getIndex();
|
||||
USERIndex = CentralProcessor.TickType.USER.getIndex();
|
||||
IOWAITIndex = CentralProcessor.TickType.IOWAIT.getIndex();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造,等待时间为用于计算在一定时长内的CPU负载情况,如传入1000表示最近1秒的负载情况
|
||||
*
|
||||
* @param processor {@link CentralProcessor}
|
||||
* @param waitingTime 设置等待时间,单位毫秒
|
||||
*/
|
||||
public CpuTicks(CentralProcessor processor, long waitingTime) {
|
||||
// CPU信息
|
||||
final long[] prevTicks = processor.getSystemCpuLoadTicks();
|
||||
|
||||
// 这里必须要设置延迟
|
||||
Util.sleep(waitingTime);
|
||||
final long[] ticks = processor.getSystemCpuLoadTicks();
|
||||
|
||||
this.idle = tick(prevTicks, ticks, IDLEIndex);
|
||||
this.nice = tick(prevTicks, ticks, NICEIndex);
|
||||
this.irq = tick(prevTicks, ticks, IRQIndex);
|
||||
this.softIrq = tick(prevTicks, ticks, SOFTIRQIndex);
|
||||
this.steal = tick(prevTicks, ticks, STEALIndex);
|
||||
this.cSys = tick(prevTicks, ticks, SYSTEMIndex);
|
||||
this.user = tick(prevTicks, ticks, USERIndex);
|
||||
this.ioWait = tick(prevTicks, ticks, IOWAITIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取CPU总的使用率
|
||||
*
|
||||
* @return CPU总使用率
|
||||
*/
|
||||
public long totalCpu() {
|
||||
return Math.max(user + nice + cSys + idle + ioWait + irq + softIrq + steal, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一段时间内的CPU负载标记差
|
||||
*
|
||||
* @param prevTicks 开始的ticks
|
||||
* @param ticks 结束的ticks
|
||||
* @param tickType tick类型
|
||||
* @return 标记差
|
||||
* @since 5.7.12
|
||||
*/
|
||||
private static long tick(long[] prevTicks, long[] ticks, int index) {
|
||||
return ticks[index] - prevTicks[index];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
71
server/src/main/java/io/wdd/rpc/status/DiskInfo.java
Normal file
71
server/src/main/java/io/wdd/rpc/status/DiskInfo.java
Normal file
@@ -0,0 +1,71 @@
|
||||
package io.wdd.rpc.status;
|
||||
|
||||
import io.wdd.common.utils.FormatUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import oshi.hardware.HWDiskStore;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public class DiskInfo {
|
||||
|
||||
String name;
|
||||
|
||||
String model;
|
||||
|
||||
String serial;
|
||||
|
||||
String size;
|
||||
|
||||
|
||||
private List<PartitionInfo> partitionInfoList;
|
||||
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
private static class PartitionInfo{
|
||||
|
||||
String path;
|
||||
|
||||
String type;
|
||||
|
||||
String size;
|
||||
|
||||
String mountPoint;
|
||||
|
||||
}
|
||||
|
||||
public static List<DiskInfo> mapFromDiskStore(List<HWDiskStore> hwDiskStoreList){
|
||||
|
||||
return hwDiskStoreList.stream().map(
|
||||
hwDiskStore -> DiskInfo.builder()
|
||||
.name(hwDiskStore.getName())
|
||||
.model(hwDiskStore.getModel())
|
||||
.serial(hwDiskStore.getSerial())
|
||||
.size(FormatUtils.formatData(hwDiskStore.getSize()))
|
||||
.partitionInfoList(
|
||||
// partition should also be got from stream
|
||||
hwDiskStore.getPartitions().stream().map(partition -> DiskInfo.PartitionInfo.builder()
|
||||
.path(partition.getIdentification())
|
||||
.size(FormatUtils.formatData(partition.getSize()))
|
||||
.type(partition.getType())
|
||||
.mountPoint(partition.getMountPoint())
|
||||
.build()
|
||||
).collect(Collectors.toList())
|
||||
)
|
||||
.build()
|
||||
).collect(Collectors.toList());
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
47
server/src/main/java/io/wdd/rpc/status/MemoryInfo.java
Normal file
47
server/src/main/java/io/wdd/rpc/status/MemoryInfo.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package io.wdd.rpc.status;
|
||||
|
||||
import io.wdd.common.utils.FormatUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import oshi.hardware.GlobalMemory;
|
||||
import oshi.hardware.VirtualMemory;
|
||||
|
||||
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public class MemoryInfo {
|
||||
|
||||
|
||||
String total;
|
||||
|
||||
String usage;
|
||||
|
||||
String available;
|
||||
|
||||
String memoryType;
|
||||
|
||||
String swapTotal;
|
||||
|
||||
String swapAvailable;
|
||||
|
||||
String swapUsage;
|
||||
|
||||
public static MemoryInfo build(GlobalMemory memory) {
|
||||
|
||||
VirtualMemory virtualMemory = memory.getVirtualMemory();
|
||||
return MemoryInfo.builder()
|
||||
.memoryType(memory.getPhysicalMemory().get(0).getMemoryType())
|
||||
.total(FormatUtils.formatData(memory.getTotal()))
|
||||
.available(FormatUtils.formatData(memory.getAvailable()))
|
||||
.usage(FormatUtils.formatData(memory.getTotal() - memory.getAvailable()))
|
||||
.swapTotal(FormatUtils.formatData(virtualMemory.getSwapTotal()))
|
||||
.swapUsage(FormatUtils.formatData(virtualMemory.getSwapUsed()))
|
||||
.swapAvailable(FormatUtils.formatData(virtualMemory.getSwapTotal() - virtualMemory.getSwapUsed()))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
18
server/src/main/java/io/wdd/rpc/status/MetricStatus.java
Normal file
18
server/src/main/java/io/wdd/rpc/status/MetricStatus.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package io.wdd.rpc.status;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 没时间整这些,反正大一点数据也无所谓 不是吗
|
||||
*/
|
||||
@Deprecated
|
||||
@Data
|
||||
public class MetricStatus {
|
||||
|
||||
CpuInfo cpuInfo;
|
||||
|
||||
MemoryInfo memoryInfo;
|
||||
|
||||
AppStatusInfo appStatus;
|
||||
|
||||
}
|
||||
108
server/src/main/java/io/wdd/rpc/status/NetworkInfo.java
Normal file
108
server/src/main/java/io/wdd/rpc/status/NetworkInfo.java
Normal file
@@ -0,0 +1,108 @@
|
||||
package io.wdd.rpc.status;
|
||||
|
||||
|
||||
import io.wdd.common.utils.FormatUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import oshi.hardware.NetworkIF;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public class NetworkInfo {
|
||||
|
||||
private String name;
|
||||
private String displayName;
|
||||
private String macAddr;
|
||||
private String mtu;
|
||||
private String[] innerIpv4Addr;
|
||||
private String publicIpv4Addr;
|
||||
private String[] innerIpv6Addr;
|
||||
private String publicIpv6Addr;
|
||||
/**
|
||||
* 过去1s内的网速,接收速率
|
||||
*/
|
||||
private String recvSpeed;
|
||||
/**
|
||||
* 过去1s内的网速,发送速率
|
||||
*/
|
||||
private String sendSpeed;
|
||||
private String trafficRecv;
|
||||
private String trafficSend;
|
||||
|
||||
public static NetworkInfo mapFromNetworkIF(NetworkIF networkIF) {
|
||||
|
||||
return NetworkInfo
|
||||
.builder()
|
||||
.name(networkIF.getName())
|
||||
.displayName(networkIF.getDisplayName())
|
||||
.mtu(String.valueOf(networkIF.getMTU()))
|
||||
.macAddr(networkIF.getMacaddr())
|
||||
.innerIpv4Addr(generateIPDICRFromNetworkIFList(
|
||||
networkIF,
|
||||
4
|
||||
))
|
||||
.innerIpv6Addr(generateIPDICRFromNetworkIFList(
|
||||
networkIF,
|
||||
6
|
||||
))
|
||||
.trafficSend(FormatUtils.formatData(networkIF.getBytesSent()))
|
||||
.trafficRecv(FormatUtils.formatData(networkIF.getBytesRecv())
|
||||
)
|
||||
.build();
|
||||
|
||||
}
|
||||
public static List<NetworkInfo> mapFromNetworkIFS(List<NetworkIF> networkIFList) {
|
||||
|
||||
return networkIFList
|
||||
.stream()
|
||||
.map(
|
||||
networkIF -> NetworkInfo
|
||||
.builder()
|
||||
.name(networkIF.getName())
|
||||
.displayName(networkIF.getDisplayName())
|
||||
.mtu(String.valueOf(networkIF.getMTU()))
|
||||
.macAddr(networkIF.getMacaddr())
|
||||
.innerIpv4Addr(generateIPDICRFromNetworkIFList(
|
||||
networkIF,
|
||||
4
|
||||
))
|
||||
.innerIpv6Addr(generateIPDICRFromNetworkIFList(
|
||||
networkIF,
|
||||
6
|
||||
))
|
||||
.trafficSend(FormatUtils.formatData(networkIF.getBytesSent()))
|
||||
.trafficRecv(FormatUtils.formatData(networkIF.getBytesRecv())
|
||||
)
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static String[] generateIPDICRFromNetworkIFList(NetworkIF networkIF, int Ipv4OrIpv6) {
|
||||
|
||||
String[] iPAddr;
|
||||
Short[] subnetMasks;
|
||||
|
||||
if (Ipv4OrIpv6 == 4) {
|
||||
iPAddr = networkIF.getIPv4addr();
|
||||
subnetMasks = networkIF.getSubnetMasks();
|
||||
} else {
|
||||
iPAddr = networkIF.getIPv6addr();
|
||||
subnetMasks = networkIF.getPrefixLengths();
|
||||
}
|
||||
|
||||
String[] result = new String[iPAddr.length];
|
||||
for (int index = 0; index < iPAddr.length; index++) {
|
||||
result[index] = iPAddr[index] + "/" + subnetMasks[index];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package io.wdd.rpc.status;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public class OctopusStatusMessage {
|
||||
|
||||
// below two will be used by both server and agent
|
||||
// 存储所有Agent的实时健康状态, 1代表健康 0代表失败
|
||||
public static final String ALL_AGENT_STATUS_REDIS_KEY = "ALL_AGENT_HEALTHY_STATUS";
|
||||
public static final String HEALTHY_STATUS_MESSAGE_TYPE = "ping";
|
||||
public static final String ALL_STATUS_MESSAGE_TYPE = "all";
|
||||
public static final String METRIC_STATUS_MESSAGE_TYPE = "metric";
|
||||
public static final String APP_STATUS_MESSAGE_TYPE = "app";
|
||||
|
||||
/**
|
||||
* which kind of status should be return
|
||||
* metric => short time message
|
||||
* all => all agent status message
|
||||
* healthy => check for healthy
|
||||
* */
|
||||
String type;
|
||||
|
||||
String agentTopicName;
|
||||
|
||||
int metricRepeatCount;
|
||||
|
||||
int metricRepeatPinch;
|
||||
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package io.wdd.server.controller;
|
||||
|
||||
|
||||
import io.wdd.common.response.R;
|
||||
import io.wdd.server.beans.vo.AppInfoVO;
|
||||
import io.wdd.server.coreService.CoreAppService;
|
||||
import io.wdd.common.beans.response.R;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package io.wdd.server.controller;
|
||||
|
||||
import io.wdd.common.response.R;
|
||||
import io.wdd.server.beans.po.DomainInfoPO;
|
||||
import io.wdd.server.beans.vo.DomainInfoVO;
|
||||
import io.wdd.server.coreService.CoreDomainService;
|
||||
import io.wdd.common.beans.response.R;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ package io.wdd.server.controller;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import io.wdd.common.beans.response.R;
|
||||
import io.wdd.common.response.R;
|
||||
import io.wdd.server.beans.po.DomainInfoPO;
|
||||
import io.wdd.server.beans.po.ServerInfoPO;
|
||||
import io.wdd.server.beans.vo.AppInfoVO;
|
||||
|
||||
161
server/src/main/resources/application.yml
Normal file
161
server/src/main/resources/application.yml
Normal file
@@ -0,0 +1,161 @@
|
||||
server:
|
||||
port: 9999
|
||||
|
||||
spring:
|
||||
main:
|
||||
allow-circular-references: true
|
||||
allow-bean-definition-overriding: true
|
||||
rabbitmq:
|
||||
host: 150.230.198.103
|
||||
port: 20672
|
||||
username: boge
|
||||
password: boge14@Level5
|
||||
virtual-host: /
|
||||
listener:
|
||||
simple:
|
||||
retry:
|
||||
# ack failed will reentrant the Rabbit Listener
|
||||
max-attempts: 2
|
||||
enabled: true
|
||||
# retry interval unit ms
|
||||
max-interval: 65000
|
||||
initial-interval: 65000
|
||||
redis:
|
||||
host: 146.56.147.12
|
||||
port: 21370
|
||||
database: 0
|
||||
password: boge14@Level5
|
||||
# cluster:
|
||||
# nodes:
|
||||
# - 43.154.83.213:21370
|
||||
# - 43.154.83.213:21371
|
||||
# - 43.154.83.213:21372
|
||||
# - 43.154.83.213:21373
|
||||
# - 43.154.83.213:21374
|
||||
# - 43.154.83.213:21375
|
||||
# # 获取失败 最大重定向次数
|
||||
# max-redirects: 3
|
||||
# timeout: 50000
|
||||
#如果用以前的jedis,可以把下面的lettuce换成jedis即可
|
||||
lettuce:
|
||||
pool:
|
||||
# 连接池最大连接数默认值为8
|
||||
max-active: 16
|
||||
# 连接池最大阻塞时间(使用负值表示没有限制)默认值为-1
|
||||
max-wait: -1
|
||||
# 连接池中最大空闲连接数默认值为8
|
||||
max-idle: 10
|
||||
# 连接池中的最小空闲连接数,默认值为0
|
||||
min-idle: 10
|
||||
time-between-eviction-runs: 50000
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://140.238.63.37:21306/wdd_server?autoReconnect=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: boge14@Level5
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
hikari:
|
||||
minimum-idle: 3
|
||||
# 空闲连接存活最大时间,默认600000(10分钟)
|
||||
idle-timeout: 180000
|
||||
# 连接池最大连接数,默认是10
|
||||
maximum-pool-size: 5
|
||||
# 此属性控制从池返回的连接的默认自动提交行为,默认值:true
|
||||
auto-commit: true
|
||||
connection-test-query: SELECT 1
|
||||
# 最大文件上传
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 500MB
|
||||
max-request-size: 500MB
|
||||
|
||||
mybatis-plus:
|
||||
type-aliases-package: io.wdd.server.beans.po
|
||||
global-config:
|
||||
db-column-underline: true
|
||||
db-config:
|
||||
# modify ethe id strategy
|
||||
id-type: assign_id
|
||||
# logic delete field globally
|
||||
logicDeleteField: isDelete
|
||||
logic-not-delete-value: 0
|
||||
logic-delete-value: 1
|
||||
banner: false
|
||||
configuration:
|
||||
# 希望知道所有的sql是怎么执行的, 配置输出日志
|
||||
#log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl
|
||||
# 数据库下划线--实体类也是下划线 需要为false
|
||||
map-underscore-to-camel-case: true
|
||||
# 一级缓存的 缓存级别默认为 session,如果要关闭一级缓存可以设置为 statement
|
||||
local-cache-scope: session
|
||||
# 是否开启二级缓存
|
||||
cache-enabled: false
|
||||
# 默认地址为 classpath*:/mapper/**/*.xml
|
||||
# mapper-locations: classpath*:/real-mappers/**/*.xml
|
||||
|
||||
octopus:
|
||||
message:
|
||||
# agent boot up default common exchange
|
||||
init_exchange: InitExchange
|
||||
# server will send message to agent using this common queue
|
||||
init_to_server: InitToServer
|
||||
# agent boot up default common exchange routing key
|
||||
init_to_server_key: InitToServerKey
|
||||
# server will receive message from agent using this common queue
|
||||
init_from_server: InitFromServer
|
||||
# agent boot up default common exchange routing key
|
||||
init_from_server_key: InitFromServerKey
|
||||
# initialization register time out (unit ms) default is 5 min
|
||||
init_ttl: "3000000"
|
||||
# Octopus Exchange Name == server comunicate with agent
|
||||
octopus_exchange: OctopusExchange
|
||||
# Octopus Message To Server == all agent send info to server queue and topic
|
||||
octopus_to_server: OctopusToServer
|
||||
executor:
|
||||
name: executor-functions
|
||||
status:
|
||||
name: octopus-agent
|
||||
healthy:
|
||||
type: cron
|
||||
cron: 10 */1 * * * ? *
|
||||
start-delay: 30
|
||||
metric:
|
||||
pinch: 20
|
||||
|
||||
oss:
|
||||
# 这里只是因为需要一个层级,不一定下面的都是oracle
|
||||
oracle:
|
||||
seoul1:
|
||||
namespace: cnk8d6fazu16
|
||||
region: ap-seoul-1
|
||||
key: aed62d24d85e2da809ce02bf272420ba4ed74820
|
||||
secret: rQdEcn69K049+JkA1IGoQmC1k8zma8zfWvZvVS0h144=
|
||||
capacity: 10737418240
|
||||
seoul2:
|
||||
namespace: cncvl8ro2rbf
|
||||
region: ap-seoul-1
|
||||
key: 9e413c6e66269bc65d7ec951d93ba9c6a9781f6e
|
||||
secret: dkXD7PysjrhsTKfNIbKupUmtxdfOvYCyLXf0MXa4hnU=
|
||||
capacity: 10737418240
|
||||
tokyo1:
|
||||
namespace: nrjcs6lwr9vy
|
||||
region: ap-tokyo-1
|
||||
key: 0584c323d6c8d24cc2fc8c2d716a4ea35bb99ae6
|
||||
secret: +xicO9obeqzC5a/WY1rXvl5pMWSWbVIpMt3Qv691NtU=
|
||||
capacity: 10737418240
|
||||
phoenix1:
|
||||
namespace: axqr6x6t48wm
|
||||
region: us-phoenix-1
|
||||
key: e87a121f1548b244c7bd649a1f0ca35195d46cf2
|
||||
secret: uT+NIgJiKPjSaPT8EVUw3xbLSCv/CFMFuebVauznafk=
|
||||
capacity: 10737418240
|
||||
london1:
|
||||
namespace: lrmzslyt8jzs
|
||||
region: uk-london-1
|
||||
key: 57671886f9f1bcc5ac7235b5a0e6123f5ca271b3
|
||||
secret: ukWae6TXjID2Wqxh+7mAPAf4busZPGzwAh/WDKZ5MOQ=
|
||||
capacity: 10737418240
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user