初始化

master
李永杰 2024-04-18 22:46:15 +08:00
parent 84702fe41c
commit b65dffd314
33 changed files with 2194 additions and 0 deletions

38
.gitignore vendored 100644
View File

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

View File

@ -0,0 +1,18 @@
package com.muyu;
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.scheduling.annotation.*;
/**
*
* @author LiYongJie
* @date 2024/4/17
*/
@SpringBootApplication
@EnableScheduling
public class LoadCenterApplication {
public static void main(String[] args) {
SpringApplication.run(LoadCenterApplication.class);
}
}

View File

@ -0,0 +1,161 @@
package com.muyu.common.aliyun;
import com.aliyun.ecs20140526.*;
import com.aliyun.ecs20140526.models.*;
import com.aliyun.tea.*;
import com.aliyun.teautil.*;
import com.aliyun.teautil.models.*;
import com.muyu.common.aliyun.config.*;
import com.muyu.common.domain.*;
import com.muyu.common.utils.*;
import lombok.extern.slf4j.*;
import org.springframework.stereotype.*;
import java.util.*;
/**
* ECSOpenAPI
* @author LiYongJie
* @date 2024/4/17
*/
@Slf4j
@Service
public class AliYunEcsService {
/**
*
*/
private final AliConfig aliConfig;
/**
*
*/
private final InstanceConfig instanceConfig;
/**
*
*/
private final Client client;
public AliYunEcsService(AliConfig aliConfig, InstanceConfig instanceConfig, Client client){
this.aliConfig = aliConfig;
this.instanceConfig = instanceConfig;
this.client = client;
}
/**
* ECS
*/
public String runInstances() throws Exception {
RunInstancesRequest request = new RunInstancesRequest()
.setRegionId(aliConfig.getRegionId())
.setImageId(instanceConfig.getImageId())
.setInstanceType(instanceConfig.getInstanceType())
.setSecurityGroupId(instanceConfig.getSecurityGroupId())
.setVSwitchId(instanceConfig.getVSwitchId())
.setInstanceName("gateway:node:test")
.setDescription(new Date().toString() + "创建的实例节点")
.setInternetMaxBandwidthOut(Integer.valueOf(instanceConfig.getInternetMaxBandwidthOut()))
.setInternetChargeType(instanceConfig.getInternetChargeType())
.setInstanceChargeType(instanceConfig.getInstanceChargeType())
.setDryRun(false)
.setSystemDisk(new RunInstancesRequest.RunInstancesRequestSystemDisk()
.setSize(instanceConfig.getSize())
.setCategory(instanceConfig.getCategory()));
String result = "";
try {
com.aliyun.teaconsole.Client.log("--------------------批量创建实例开始--------------------");
RunInstancesResponse responces = client.runInstances(request);
com.aliyun.teaconsole.Client.log("--------------------创建实例成功实例ID:" + com.aliyun.teautil.Common.toJSONString(responces.body.instanceIdSets.instanceIdSet) + "--------------------");
//返回实例ID
result = responces.body.instanceIdSets.instanceIdSet + "";//前后带 []
result = UserUtil.removeBrackets(result);//前后不带[]
} catch (TeaException error) {
com.aliyun.teaconsole.Client.log("--------------------创建实例失败:" + com.aliyun.teautil.Common.toJSONString(error.code) + "--------------------" + error.message);
} catch (Exception _error) {
TeaException error = new TeaException(_error.getMessage(), _error);
com.aliyun.teaconsole.Client.log("--------------------创建实例失败:" + com.aliyun.teautil.Common.toJSONString(error.code) + "--------------------" + error.message);
}
return result;
}
/**
* ID
*/
public EcsInstanceInfo selectList(String instanceId) throws Exception{
DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest()
.setRegionId(aliConfig.getRegionId())
.setInstanceName("*")
.setInstanceIds(Common.toJSONString(com.aliyun.darabonbastring.Client.split(instanceId, ",", 50)))
.setPageSize(10);
// 初始化返回值
List<DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance> instanceList = null;
try {
DescribeInstancesResponse describeInstancesResponse = client.describeInstancesWithOptions(describeInstancesRequest, new RuntimeOptions());
DescribeInstancesResponseBody body = describeInstancesResponse.getBody();
DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstances instances = body.getInstances();
instanceList = instances.getInstance();
if (null != instanceList || instanceList.isEmpty()){
return new EcsInstanceInfo();
}
EcsInstanceInfo ecsInstanceInfo = new EcsInstanceInfo();
instanceList.forEach(item -> {
ecsInstanceInfo.setInstanceId(item.getInstanceId());
ecsInstanceInfo.setInstanceName(item.getInstanceName());
ecsInstanceInfo.setStatus(item.status);
ecsInstanceInfo.setPublicIpAddress(UserUtil.removeBrackets(item.getPublicIpAddress().getIpAddress().toString()));
ecsInstanceInfo.setRecyclable(item.getRecyclable());
ecsInstanceInfo.setPrivateIpAddress(item.getVpcAttributes().getPrivateIpAddress().toString());
});
return ecsInstanceInfo;
} catch (TeaException e) {
e.printStackTrace();
log.error("code:【{}】,message:【{}】,data:【{}】",e.code,e.message,e.data);
log.error(e.toString());
log.error(e.getData().get("Recommend").toString());
com.aliyun.teautil.Common.assertAsString(e.message);
}catch (Exception error){
TeaException exception = new TeaException(error.getMessage(), error);
log.error("message:【{}】",error.getMessage(),error);
log.error(exception.message);
log.error(exception.getData().get("Recommend").toString());
com.aliyun.teautil.Common.assertAsString(exception.message);
}
return new EcsInstanceInfo();
}
/**
*
*/
public void deleteEcs(String instanceId) throws Exception{
DeleteInstancesRequest deleteInstancesRequest = new DeleteInstancesRequest()
.setRegionId(aliConfig.getRegionId())
.setDryRun(false)
.setForce(true)
.setTerminateSubscription(false)
.setInstanceId(Arrays.asList(instanceId));
try {
// 复制代码运行请自行打印 API 的返回值
client.deleteInstancesWithOptions(deleteInstancesRequest, new RuntimeOptions());
} catch (TeaException error) {
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
// 错误 message
log.error("code:[{}], message: [{}],data: [{}]",error.getCode(),error.getMessage(),error.getData());
System.out.println(error);
// 诊断地址
System.out.println(error.getData().get("Recommend"));
com.aliyun.teautil.Common.assertAsString(error);
} catch (Exception _error) {
TeaException error = new TeaException(_error.getMessage(), _error);
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
// 错误 message
log.error("message: [{}]",_error.getMessage());
}
}
}

View File

@ -0,0 +1,42 @@
package com.muyu.common.aliyun.config;
import com.aliyun.ecs20140526.*;
import com.aliyun.teaopenapi.models.*;
import lombok.*;
import org.springframework.boot.context.properties.*;
import org.springframework.context.annotation.*;
import java.io.*;
/**
*
*
* @author LiYongJie
* @date 2024/4/17
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "config.ali")
public class AliConfig implements Serializable {
/**
*
*/
private String accessKeyId;
/**
*
*/
private String accessKeySecret;
/**
* ID
*/
private String regionId;
@Bean
public static Client createEcsClient(AliConfig aliConfig) throws Exception {
Config config = new Config()
.setAccessKeyId(aliConfig.getAccessKeyId())
.setAccessKeySecret(aliConfig.getAccessKeySecret())
.setRegionId(aliConfig.getRegionId());
return new Client(config);
}
}

View File

@ -0,0 +1,59 @@
package com.muyu.common.aliyun.config;
import lombok.*;
import org.springframework.boot.context.properties.*;
import org.springframework.context.annotation.*;
import java.io.*;
/**
* yml
*
* @author LiYongJie
* @date 2024/4/17
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "config.instance")
public class InstanceConfig implements Serializable {
/**
* ID
*/
private String regionId;
/**
* ID
*/
private String imageId;
/**
*
*/
private String instanceType;
/**
* ID
*/
private String securityGroupId;
/**
* ID
*/
private String vSwitchId;
/**
* Mbit/s, 1~100,0
*/
private String internetMaxBandwidthOut;
/**
*
*/
private String size;
/**
*
*/
private String category;
/**
* ECS
*/
private String instanceChargeType;
/**
*
*/
private String internetChargeType;
}

View File

@ -0,0 +1,38 @@
package com.muyu.common.aliyun.config;
import com.alibaba.fastjson2.*;
import lombok.extern.slf4j.*;
import okhttp3.*;
/**
* mqtt
* @author liyongjie
* @date 2024/4/17
*/
@Slf4j
public class MqttInfoClient {
public static final String URL = "http://10.10.26.5:8080/public/cluster";
public static void main(String[] args) {
OkHttpClient client = new OkHttpClient();
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.parse(response.body().string());
JSONObject jsonObject = jsonArray.getJSONObject(0);
JSONObject mqttInfo = jsonObject.getJSONObject("mqttInfo");
int connectSize = mqttInfo.getIntValue("connectSize");
log.info(connectSize + "");
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,27 @@
package com.muyu.common.aliyun.module;
import lombok.*;
import java.io.*;
import java.util.*;
/**
* ECS
*
* @author LiYongJie
* @date 2024/4/17
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class EcsSelectModule implements Serializable {
/**
* ID
*/
private List<String> instanceIdList;
/**
*
*/
private List<String> instanceNameList;
}

View File

@ -0,0 +1,20 @@
package com.muyu.common.domain;
import lombok.*;
/**
*
* @author LiYongJie
* @date 2024/4/17
*/
@Data
public class ApiFoxModule {
/**
* ID
*/
private String clusterId;
/*
* CPU使
*/
private CPUInfo cupInfo;
}

View File

@ -0,0 +1,38 @@
package com.muyu.common.domain;
import lombok.*;
import java.io.*;
/**
* CPU使
*
* @author LiYongJie
* @date 2024/4/17
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CPUInfo implements Serializable {
/**
* CPU
*/
private long cpuNum;
/**
* 使
*/
private String cSys;
/**
*
*/
private String idle;
/**
* I/O
*/
private String iowait;
/**
* 使
*/
private String user;
}

View File

@ -0,0 +1,45 @@
package com.muyu.common.domain;
import lombok.*;
import java.io.*;
/**
*
* @author LiYongJie
* @date 2024/4/17
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class EcsInstanceInfo implements Serializable {
/**
* ID
*/
private String instanceId;
/**
*
*/
private String instanceName;
/**
*
*/
private String status;
/**
* IP
*/
private String publicIpAddress;
/**
* IP
*/
private String privateIpAddress;
/**
*
*/
private String creationTime;
/**
*
*/
private boolean recyclable;
}

View File

@ -0,0 +1,39 @@
package com.muyu.common.domain;
import lombok.*;
import java.io.*;
/**
*
*
* @author LiYongJie
* @date 2024/4/17
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class FlowInfo implements Serializable {
/**
*
*/
private String lastReadThroughput;
/**
*
*/
private String lastWriteThroughput;
/**
*
*/
private String readByBytesHistory;
/**
*
*/
private String readBytes;
/**
*
*/
private String writeBytesHistory;
}

View File

@ -0,0 +1,57 @@
package com.muyu.common.domain;
import lombok.*;
import java.io.*;
/**
* JVM使
* @author LiYongJie
* @date 2024/4/17
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class JVMInfo implements Serializable {
/**
* ()
*/
private String fileDescriptors;
/**
*
*/
private String heapCommit;
/**
*
*/
private String heapInit;
/**
*
*/
private String heapMax;
/**
* 使
*/
private String heapUsed;
/**
* Java
*/
private String jdkHome;
/**
* jdk
*/
private String jdkVersion;
/**
*
*/
private String noHeapInit;
/**
* 使
*/
private String noHeapUsed;
/**
* 线
*/
private long threadCount;
}

View File

@ -0,0 +1,159 @@
package com.muyu.common.domain;
import lombok.*;
import java.io.*;
/**
*
*
* @author LiYongJie
* @date 2024/4/18
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> implements Serializable {
/**
*
*/
public static final int SUCCESS = 200;
/**
*
*/
public static final int FAIL = 500;
/**
*
*/
private static final int WARN = 501;
/**
*
*/
private static final long serialVersionUID = 1L;
/**
*
*/
private int code;
/**
*
*/
private String msg;
/**
*
*/
private T data;
public static <T> Result<T> buildCode(int code, String msg, T data) {
return restResult(data, code, msg);
}
public static <T> Result<T> success() {
return restResult(null, SUCCESS, null);
}
public static <T> Result<T> success(T data) {
return restResult(data, SUCCESS, null);
}
public static <T> Result<T> success(T data, String msg) {
return restResult(data, SUCCESS, msg);
}
public static <T> Result<T> error() {
return restResult(null, FAIL, null);
}
public static <T> Result<T> error(T data) {
return restResult(data, FAIL, null);
}
public static <T> Result<T> error(String msg) {
return restResult(null, FAIL, msg);
}
public static <T> Result<T> error(T data, String msg) {
return restResult(data, FAIL, msg);
}
public static <T> Result<T> error(int code, String msg) {
return restResult(null, code, msg);
}
public static <T> Result<T> warn() {
return restResult(null, WARN, null);
}
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, null);
}
public static <T> Result<T> warn(T data, String msg) {
return restResult(null, WARN, msg);
}
public static <T> Result<T> warn(int code, String msg) {
return restResult(null, code, msg);
}
private static <T> Result<T> restResult(T data, int code, String msg) {
return Result.<T>builder()
.code(code)
.data(data)
.msg(msg)
.build();
}
public static <T> Boolean isError(Result<T> ret) {
return !isSuccess(ret);
}
private static <T> boolean isSuccess(Result<T> ret) {
return Result.SUCCESS == ret.getCode();
}
/**
* Mqtt
* @author LiYongJie
* @date 2024/4/18
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class MqttInfo implements Serializable {
/**
*
*/
private long closeEventSize;
/**
*
*/
private long connectEventSize;
/**
*
*/
private long connectSize;
/**
*
*/
private long disconnectEventSize;
/**
*
*/
private long publishEventSize;
/**
*
*/
private long publishRetryEventSize;
/**
*
*/
private long retainSize;
}
}

View File

@ -0,0 +1,25 @@
package com.muyu.common.domain;
import lombok.*;
import java.io.*;
/**
*
* @author LiYongJie
* @date 2024/4/18
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WorkGatewayNode implements Serializable {
/**
* IP
*/
private String nodeId;
/**
*
*/
private String weight;
}

View File

@ -0,0 +1,59 @@
package com.muyu.common.gateway.cache;
import com.muyu.common.gateway.cache.abs.*;
import com.muyu.common.redis.service.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
import java.util.*;
/**
*
* @author LiYongJie
* @date 2024/4/18
*/
@Component
public class GatewayLoadNodeCache extends GatewayCacheAbs<String> {
@Autowired
private RedisService redisService;
/**
* key
*/
public static final String gatewayLoadNodeKey = "node";
@Override
public String getPre(){
return "gateway:load:";
}
/**
*
* @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 (null == index || index > 100){
throw new RuntimeException("下标越界,0~100");
}
return redisService.getCacheListValue(enCode(gatewayLoadNodeKey), index);
}
}

View File

@ -0,0 +1,65 @@
package com.muyu.common.gateway.cache;
import com.muyu.common.gateway.cache.abs.GatewayCacheAbs;
import com.muyu.common.redis.service.*;
import lombok.extern.java.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.*;
import javax.annotation.*;
/**
*
* @author LiYongJie
* @date 2024/4/18
*/
@Component
public class GatewayLoadSeriesCache extends GatewayCacheAbs<String> {
/**
* redis
*/
@Autowired
private RedisService redisService;
/**
*
*/
public static final String gatewayLoadSeriesKey = "series";
@Override
public String getPre() {
return "gateway:load:";
}
/**
* bean
*/
@PostConstruct
public void init(){
redisService.setCacheObject(enCode(gatewayLoadSeriesKey), 0L);
}
/**
*
* @return
*/
public Long get(){
return redisService.getCacheObject(enCode(gatewayLoadSeriesKey));
}
/**
*
* @return
*/
public Long incrementAndGet(){
return redisService.increment(enCode(gatewayLoadSeriesKey), 1L);
}
/**
*
*/
public void reset(){
this.init();
}
}

View File

@ -0,0 +1,53 @@
package com.muyu.common.gateway.cache;
import com.muyu.common.gateway.cache.abs.GatewayCacheAbs;
import com.muyu.common.gateway.module.*;
import com.muyu.common.redis.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.*;
/**
*
* @author LiYongJie
* @date 2024/4/18
*/
@Component
public class GatewayNodeCache extends GatewayCacheAbs<String> {
/**
* redis
*/
@Autowired
private RedisService redisService;
@Override
public String getPre(){
return "gateway:node:info";
}
/**
*
* @param gatewayNodeInfo
*/
public void put(GatewayNodeInfo gatewayNodeInfo){
redisService.setCacheObject(enCode(gatewayNodeInfo.getNodeId()), gatewayNodeInfo);
}
/**
*
* @param nodeId ID
* @return
*/
public GatewayNodeInfo get(String nodeId){
return redisService.getCacheObject(enCode(nodeId));
}
/**
*
* @param nodeId ID
*/
public void remove(String nodeId){
redisService.deleteObject(enCode(nodeId));
}
}

View File

@ -0,0 +1,9 @@
package com.muyu.common.gateway.cache;
/**
*
* @author LiYongJie
* @date 2024/4/18
*/
public class GatewayNodeScoreCache {
}

View File

@ -0,0 +1,9 @@
package com.muyu.common.gateway.cache;
/**
* VIN
* @author LiYongJie
* @date 2024/4/18
*/
public class GatewayNodeSetVinCache {
}

View File

@ -0,0 +1,9 @@
package com.muyu.common.gateway.cache;
/**
*
* @author LiYongJie
* @date 2024/4/18
*/
public class GatewayVehicleLineNodeCache {
}

View File

@ -0,0 +1,26 @@
package com.muyu.common.gateway.cache.abs;
import com.muyu.common.redis.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.*;
/**
*
* @author LiYongJie
* @date 2024/4/18
*/
public abstract class GatewayCacheAbs<K> {
/**
* redis
*/
@Autowired
private RedisService redisService;
public abstract String getPre();
public String enCode(K key){
return getPre() + key;
}
}

View File

@ -0,0 +1,29 @@
package com.muyu.common.gateway.module;
import lombok.*;
import java.io.*;
/**
*
* @author LiYongJie
* @date 2024/4/18
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class GatewayNodeInfo implements Serializable {
/**
* ID
*/
private String nodeId;
/**
* IP
*/
private String publicIdAddress;
/**
* IP
*/
private String privateIdAddress;
}

View File

@ -0,0 +1,51 @@
package com.muyu.common.redis.configure;
import com.alibaba.fastjson2.*;
import com.alibaba.fastjson2.filter.*;
import org.springframework.data.redis.serializer.*;
import java.nio.charset.*;
/**
* Redis使FastJson
*
* @author muyu
*/
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
{
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
public static final String[] JSON_WHITELIST_STR = { "org.springframework", "com.muyu" };
static final Filter AUTO_TYPE_FILTER = JSONReader.autoTypeFilter( JSON_WHITELIST_STR);
private Class<T> clazz;
public FastJson2JsonRedisSerializer(Class<T> clazz)
{
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException
{
if (t == null)
{
return new byte[0];
}
return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException
{
if (bytes == null || bytes.length <= 0)
{
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return JSON.parseObject(str, clazz, AUTO_TYPE_FILTER);
}
}

View File

@ -0,0 +1,41 @@
package com.muyu.common.redis.configure;
import org.springframework.boot.autoconfigure.*;
import org.springframework.boot.autoconfigure.data.redis.*;
import org.springframework.cache.annotation.*;
import org.springframework.context.annotation.*;
import org.springframework.data.redis.connection.*;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.*;
/**
* redis
*
* @author muyu
*/
@Configuration
@EnableCaching
@AutoConfigureBefore(RedisAutoConfiguration.class)
public class RedisConfig extends CachingConfigurerSupport
{
@Bean
@SuppressWarnings(value = { "unchecked", "rawtypes" })
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
{
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
// 使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
// Hash的key也采用StringRedisSerializer的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}

View File

@ -0,0 +1,279 @@
package com.muyu.common.redis.service;
import org.springframework.beans.factory.annotation.*;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
/**
* Spring redis
*
* @author muyu
* @date 2024/4/18
*/
@SuppressWarnings(value = {"unchecked", "rawtypes"})
@Component
public class RedisService implements Serializable {
@Autowired
private RedisTemplate redisTemplate;
/**
* IntegerString
*
* @param key
* @param value
*/
public <T> void setCacheObject(final String key, final T value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* IntegerString
*
* @param key
* @param value
* @param timeout
* @param timeUnit
*/
public <T> void setCacheObject(final String key, final T value, final long timeout, final TimeUnit timeUnit) {
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
/**
*
*
* @param key Redis
* @param timeout
* @return true=false=
*/
public boolean expire(final String key, final long timeout) {
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
*
*
* @param key Redis
* @param timeout
* @param unit
* @return true=false=
*/
public boolean expire(final String key, final long timeout, final TimeUnit unit) {
return redisTemplate.expire(key, timeout, unit);
}
/**
*
*
* @param key Redis
* @return
*/
public long getExpire(final String key) {
return redisTemplate.getExpire(key);
}
/**
* key
*
* @param key
* @return true false
*/
public Boolean hasKey(String key) {
return redisTemplate.hasKey(key);
}
/**
*
*
* @param key
* @return
*/
public <T> T getCacheObject(final String key) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
/**
*
*
* @param key
*/
public boolean deleteObject(final String key) {
return redisTemplate.delete(key);
}
/**
*
*
* @param collection
* @return
*/
public boolean deleteObject(final Collection collection) {
return redisTemplate.delete(collection) > 0;
}
/**
* List
*
* @param key
* @param dataList List
* @return
*/
public <T> long setCacheList(final String key, final List<T> dataList) {
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
return count == null ? 0 : count;
}
/**
* list
*
* @param key
* @return
*/
public <T> List<T> getCacheList(final String key) {
return redisTemplate.opsForList().range(key, 0, -1);
}
public <T> T getCacheListValue(final String key, long index) {
return (T) redisTemplate.opsForList().index(key, index);
}
/**
* Set
*
* @param key
* @param dataSet
* @return
*/
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet) {
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
Iterator<T> it = dataSet.iterator();
while (it.hasNext()) {
setOperation.add(it.next());
}
return setOperation;
}
/**
* set
*
* @param key
* @return
*/
public <T> Set<T> getCacheSet(final String key) {
return redisTemplate.opsForSet().members(key);
}
/**
* Map
*
* @param key
* @param dataMap
*/
public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
if (dataMap != null) {
redisTemplate.opsForHash().putAll(key, dataMap);
}
}
/**
* Map
*
* @param key
* @return
*/
public <T> Map<String, T> getCacheMap(final String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* Hash
*
* @param key Redis
* @param hKey Hash
* @param value
*/
public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
redisTemplate.opsForHash().put(key, hKey, value);
}
/**
* Hash
*
* @param key Redis
* @param hKey Hash
* @return Hash
*/
public <T> T getCacheMapValue(final String key, final String hKey) {
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
return opsForHash.get(key, hKey);
}
/**
* Hash
*
* @param key Redis
* @param hKeys Hash
* @return Hash
*/
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<?> hKeys) {
return redisTemplate.opsForHash().multiGet(key, hKeys);
}
/**
* redishashKey
*
* @param key redis
* @param hashKey hash
*/
public boolean hashKey(final String key, final String hashKey) {
return this.redisTemplate.opsForHash().hasKey(key, hashKey);
}
/**
* Hash
*
* @param key Redis
* @param hKey Hash
* @return
*/
public boolean deleteCacheMapValue(final String key, final String hKey) {
return redisTemplate.opsForHash().delete(key, hKey) > 0;
}
/**
*
*
* @param pattern
* @return
*/
public Collection<String> keys(final String pattern) {
return redisTemplate.keys(pattern);
}
/**
*
*
* @param key key
* @param number
* @return
*/
public Long decrement(final String key, Long number) {
return redisTemplate.opsForValue().decrement(key, number);
}
/**
*
*
* @param key key
* @param number
* @return
*/
public Long increment(final String key, Long number) {
return redisTemplate.opsForValue().increment(key, number);
}
}

View File

@ -0,0 +1,52 @@
package com.muyu.common.utils;
import com.muyu.common.aliyun.utils.uuid.*;
import com.muyu.common.redis.service.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
import java.util.concurrent.*;
/**
*
* @Author: LiuYunHu
* @CreateTime: 2024/4/13
*/
@Component
public class UserUtil {
@Autowired
private RedisService redisService;
/*
* @Author: LiuYunHu
* @Date: 2024/4/13 9:25
* @Description: []
* @Param: [input]
* @Return: java.lang.String
**/
public static String removeBrackets(String input) {
// 使用正则表达式匹配并移除括号
String pattern = "\\[|\\]"; // 匹配 [ 或 ]
return input.replaceAll(pattern, "");
}
/*
* @Author: LiuYunHu
* @Date: 2024/4/13 11:42
* @Description: token
* @Param:
* @Return:
**/
public String getToken(String instanceIp) {
//生成令牌
String randomUUID = IdUtils.randomUUID();
//缓存两分钟
redisService.setCacheObject("lyhToken:" + instanceIp, randomUUID, 2L, TimeUnit.MINUTES);
//令牌返回
return randomUUID;
}
}

View File

@ -0,0 +1,44 @@
package com.muyu.common.utils.uuid;
/**
* ID
*
* @author couplet
*/
public class IdUtils {
/**
* UUID
*
* @return UUID
*/
public static String randomUUID () {
return UUID.randomUUID().toString();
}
/**
* UUID线
*
* @return UUID线
*/
public static String simpleUUID () {
return UUID.randomUUID().toString(true);
}
/**
* UUID使ThreadLocalRandomUUID
*
* @return UUID
*/
public static String fastUUID () {
return UUID.fastUUID().toString();
}
/**
* UUID线使ThreadLocalRandomUUID
*
* @return UUID线
*/
public static String fastSimpleUUID () {
return UUID.fastUUID().toString(true);
}
}

View File

@ -0,0 +1,447 @@
package com.muyu.common.utils.uuid;
import java.security.*;
import java.util.*;
import java.util.concurrent.*;
/**
* universally unique identifierUUID
*
* @author couplet
*/
public final class UUID implements java.io.Serializable, Comparable<UUID> {
private static final long serialVersionUID = -1185015143654744140L;
/**
* UUID64
*/
private final long mostSigBits;
/**
* UUID64
*/
private final long leastSigBits;
/**
*
*
* @param data
*/
private UUID (byte[] data) {
long msb = 0;
long lsb = 0;
assert data.length == 16 : "data must be 16 bytes in length";
for (int i = 0 ; i < 8 ; i++) {
msb = (msb << 8) | (data[i] & 0xff);
}
for (int i = 8 ; i < 16 ; i++) {
lsb = (lsb << 8) | (data[i] & 0xff);
}
this.mostSigBits = msb;
this.leastSigBits = lsb;
}
/**
* 使 UUID
*
* @param mostSigBits {@code UUID} 64
* @param leastSigBits {@code UUID} 64
*/
public UUID (long mostSigBits, long leastSigBits) {
this.mostSigBits = mostSigBits;
this.leastSigBits = leastSigBits;
}
/**
* 4UUID
*
* @return {@code UUID}
*/
public static UUID fastUUID () {
return randomUUID(false);
}
/**
* 4UUID 使 UUID
*
* @return {@code UUID}
*/
public static UUID randomUUID () {
return randomUUID(true);
}
/**
* 4UUID 使 UUID
*
* @param isSecure 使{@link SecureRandom}
*
* @return {@code UUID}
*/
public static UUID randomUUID (boolean isSecure) {
final Random ng = isSecure ? Holder.numberGenerator : getRandom();
byte[] randomBytes = new byte[16];
ng.nextBytes(randomBytes);
randomBytes[6] &= 0x0f; /* clear version */
randomBytes[6] |= 0x40; /* set to version 4 */
randomBytes[8] &= 0x3f; /* clear variant */
randomBytes[8] |= 0x80; /* set to IETF variant */
return new UUID(randomBytes);
}
/**
* 3UUID
*
* @param name UUID
*
* @return {@code UUID}
*/
public static UUID nameUUIDFromBytes (byte[] name) {
MessageDigest md;
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nsae) {
throw new InternalError("MD5 not supported");
}
byte[] md5Bytes = md.digest(name);
md5Bytes[6] &= 0x0f; /* clear version */
md5Bytes[6] |= 0x30; /* set to version 3 */
md5Bytes[8] &= 0x3f; /* clear variant */
md5Bytes[8] |= 0x80; /* set to IETF variant */
return new UUID(md5Bytes);
}
/**
* {@link #toString()} {@code UUID}
*
* @param name {@code UUID}
*
* @return {@code UUID}
*
* @throws IllegalArgumentException name {@link #toString}
*/
public static UUID fromString (String name) {
String[] components = name.split("-");
if (components.length != 5) {
throw new IllegalArgumentException("Invalid UUID string: " + name);
}
for (int i = 0 ; i < 5 ; i++) {
components[i] = "0x" + components[i];
}
long mostSigBits = Long.decode(components[0]).longValue();
mostSigBits <<= 16;
mostSigBits |= Long.decode(components[1]).longValue();
mostSigBits <<= 16;
mostSigBits |= Long.decode(components[2]).longValue();
long leastSigBits = Long.decode(components[3]).longValue();
leastSigBits <<= 48;
leastSigBits |= Long.decode(components[4]).longValue();
return new UUID(mostSigBits, leastSigBits);
}
/**
* hex
*
* @param val
* @param digits
*
* @return
*/
private static String digits (long val, int digits) {
long hi = 1L << (digits * 4);
return Long.toHexString(hi | (val & (hi - 1))).substring(1);
}
/**
* {@link SecureRandom} (RNG)
*
* @return {@link SecureRandom}
*/
public static SecureRandom getSecureRandom () {
try {
return SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
/**
* <br>
* ThreadLocalRandomJDK 7线
*
* @return {@link ThreadLocalRandom}
*/
public static ThreadLocalRandom getRandom () {
return ThreadLocalRandom.current();
}
/**
* UUID 128 64
*
* @return UUID 128 64
*/
public long getLeastSignificantBits () {
return leastSigBits;
}
/**
* UUID 128 64
*
* @return UUID 128 64
*/
public long getMostSignificantBits () {
return mostSigBits;
}
/**
* {@code UUID} . {@code UUID}
* <p>
* :
* <ul>
* <li>1 UUID
* <li>2 DCE UUID
* <li>3 UUID
* <li>4 UUID
* </ul>
*
* @return {@code UUID}
*/
public int version () {
// Version is bits masked by 0x000000000000F000 in MS long
return (int) ((mostSigBits >> 12) & 0x0f);
}
/**
* {@code UUID} {@code UUID}
* <p>
*
* <ul>
* <li>0 NCS
* <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF&nbsp;RFC&nbsp;4122</a>(Leach-Salz),
* <li>6
* <li>7 使
* </ul>
*
* @return {@code UUID}
*/
public int variant () {
// This field is composed of a varying number of bits.
// 0 - - Reserved for NCS backward compatibility
// 1 0 - The IETF aka Leach-Salz variant (used by this class)
// 1 1 0 Reserved, Microsoft backward compatibility
// 1 1 1 Reserved for future definition.
return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
}
/**
* UUID
*
* <p>
* 60 {@code UUID} time_lowtime_mid time_hi <br>
* 100 UTC 1582 10 15
*
* <p>
* UUID version 1<br>
* {@code UUID} UUID UnsupportedOperationException
*
* @throws UnsupportedOperationException {@code UUID} version 1 UUID
*/
public long timestamp () throws UnsupportedOperationException {
checkTimeBase();
return (mostSigBits & 0x0FFFL) << 48//
| ((mostSigBits >> 16) & 0x0FFFFL) << 32//
| mostSigBits >>> 32;
}
/**
* UUID
*
* <p>
* 14 UUID clock_seq clock_seq UUID
* <p>
* {@code clockSequence} UUID version 1 UUID UUID
* UnsupportedOperationException
*
* @return {@code UUID}
*
* @throws UnsupportedOperationException UUID version 1
*/
public int clockSequence () throws UnsupportedOperationException {
checkTimeBase();
return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
}
/**
* UUID
*
* <p>
* 48 UUID node IEEE 802 UUID
* <p>
* UUID version 1<br>
* UUID UUID UnsupportedOperationException
*
* @return {@code UUID}
*
* @throws UnsupportedOperationException UUID version 1
*/
public long node () throws UnsupportedOperationException {
checkTimeBase();
return leastSigBits & 0x0000FFFFFFFFFFFFL;
}
/**
* {@code UUID}
*
* <p>
* UUID BNF
*
* <pre>
* {@code
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
* time_low = 4*<hexOctet>
* time_mid = 2*<hexOctet>
* time_high_and_version = 2*<hexOctet>
* variant_and_sequence = 2*<hexOctet>
* node = 6*<hexOctet>
* hexOctet = <hexDigit><hexDigit>
* hexDigit = [0-9a-fA-F]
* }
* </pre>
*
* </blockquote>
*
* @return {@code UUID}
*
* @see #toString(boolean)
*/
@Override
public String toString () {
return toString(false);
}
/**
* {@code UUID}
*
* <p>
* UUID BNF
*
* <pre>
* {@code
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
* time_low = 4*<hexOctet>
* time_mid = 2*<hexOctet>
* time_high_and_version = 2*<hexOctet>
* variant_and_sequence = 2*<hexOctet>
* node = 6*<hexOctet>
* hexOctet = <hexDigit><hexDigit>
* hexDigit = [0-9a-fA-F]
* }
* </pre>
*
* </blockquote>
*
* @param isSimple '-'UUID
*
* @return {@code UUID}
*/
public String toString (boolean isSimple) {
final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
// time_low
builder.append(digits(mostSigBits >> 32, 8));
if (false == isSimple) {
builder.append('-');
}
// time_mid
builder.append(digits(mostSigBits >> 16, 4));
if (false == isSimple) {
builder.append('-');
}
// time_high_and_version
builder.append(digits(mostSigBits, 4));
if (false == isSimple) {
builder.append('-');
}
// variant_and_sequence
builder.append(digits(leastSigBits >> 48, 4));
if (false == isSimple) {
builder.append('-');
}
// node
builder.append(digits(leastSigBits, 12));
return builder.toString();
}
// Comparison Operations
/**
* UUID
*
* @return UUID
*/
@Override
public int hashCode () {
long hilo = mostSigBits ^ leastSigBits;
return ((int) (hilo >> 32)) ^ (int) hilo;
}
// -------------------------------------------------------------------------------------------------------------------
// Private method start
/**
*
* <p>
* {@code null} UUID UUID varriant {@code true}
*
* @param obj
*
* @return {@code true} {@code false}
*/
@Override
public boolean equals (Object obj) {
if ((null == obj) || (obj.getClass() != UUID.class)) {
return false;
}
UUID id = (UUID) obj;
return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
}
/**
* UUID UUID
*
* <p>
* UUID UUID UUID UUID UUID
*
* @param val UUID UUID
*
* @return UUID val -10 1
*/
@Override
public int compareTo (UUID val) {
// The ordering is intentionally set up so that the UUIDs
// can simply be numerically compared as two numbers
return (this.mostSigBits < val.mostSigBits ? -1 : //
(this.mostSigBits > val.mostSigBits ? 1 : //
(this.leastSigBits < val.leastSigBits ? -1 : //
(this.leastSigBits > val.leastSigBits ? 1 : //
0))));
}
/**
* time-basedUUID
*/
private void checkTimeBase () {
if (version() != 1) {
throw new UnsupportedOperationException("Not a time-based UUID");
}
}
/**
* SecureRandom
*/
private static class Holder {
static final SecureRandom numberGenerator = getSecureRandom();
}
}

View File

@ -0,0 +1,26 @@
package com.muyu.server.controller;
import com.muyu.common.domain.*;
import com.muyu.server.service.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.web.bind.annotation.*;
/**
*
* @author LiYongJie
* @date 2024/4/18
*/
@RestController
@RequestMapping("/gateway")
public class GatewayController {
/**
*
*/
@Autowired
private GatewayLoadService gatewayLoadService;
@GetMapping("/load/node")
public Result<String> loadNode(){
return Result.success(gatewayLoadService.loadNode());
}
}

View File

@ -0,0 +1,14 @@
package com.muyu.server.service;
/**
*
* @Author LiYongJie
* @Date 2024/4/18
*/
public interface GatewayLoadService {
/**
*
* @return
*/
String loadNode();
}

View File

@ -0,0 +1,50 @@
package com.muyu.server.service.impl;
import com.muyu.common.gateway.cache.*;
import com.muyu.common.gateway.module.*;
import com.muyu.server.service.*;
import lombok.*;
import org.springframework.stereotype.*;
/**
*
* @author LiYongJie
* @date 2024/4/18
*/
@Service
@AllArgsConstructor
public class GatewayLoadServiceImpl implements GatewayLoadService {
/**
*
*/
public static final Long nodeLength = 100L;
/**
*
*/
private final GatewayLoadNodeCache gatewayLoadNodeCache;
/**
*
*/
private final GatewayLoadSeriesCache gatewayLoadSeriesCache;
/**
*
*/
private final GatewayNodeCache gatewayNodeCache;
/**
*
* @return
*/
@Override
public String loadNode() {
Long seriesLoad = gatewayLoadSeriesCache.incrementAndGet();
Long seriesLoadIndex = seriesLoad % nodeLength;
String loadNodeId = gatewayLoadNodeCache.getByIndex(seriesLoadIndex);
GatewayNodeInfo gatewayNodeInfo = gatewayNodeCache.get(loadNodeId);
return gatewayNodeInfo.getPublicIdAddress();
}
}

View File

@ -0,0 +1,24 @@
# Tomcat
server:
port: 9010
Spring:
redis:
host: 120.27.163.37
port: 6379
password: Lzk750110.ylyyds!
config:
ali:
access-key-id: LTAI5tANGefs2gi8nsu4AoSZ
access-key-secret: Ut5RaJvvG7dP8hgK82qjdtvyUA6x8g
region-id: cn-zhangjiakou
instance:
image-id: m-8vb2cpmwwggxp598kjue
instance-type: ecs.g6.large
security-group-id: sg-8vbamw309ei7fz4vucfb
internet-max-bandwidth-out: 5
size: 20
category: cloud_ssd
instance-charge-type: PostPaid
internet-charge-type: PayByTraffic

View File

@ -0,0 +1,141 @@
package com.muyu;
import com.muyu.common.redis.service.*;
import lombok.*;
import lombok.extern.slf4j.*;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.context.*;
import java.util.*;
import java.util.concurrent.*;
/**
*
*
* @author LiYongJie
* @date 2024/4/18
*/
@Slf4j
@SpringBootTest(classes = LoadCenterApplication.class)
public class LoadTest {
/**
* redis
*/
@Autowired
private RedisService redisService;
@Test
public void load() {
// 初始化序列
redisService.setCacheObject("cursor", 0);
List<WorkGatewayNode> nodeIdList = new ArrayList<>() {{
add(new WorkGatewayNode("work-gateway-node-A", 8));
add(new WorkGatewayNode("work-gateway-node-B", 12));
add(new WorkGatewayNode("work-gateway-node-C", 2));
add(new WorkGatewayNode("work-gateway-node-D", 39));
add(new WorkGatewayNode("work-gateway-node-E", 39));
}};
// 权重100%
List<String> loadNodeList = new ArrayList<>();
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) {
Integer 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;
}
redisService.deleteObject("work:node:gateway");
redisService.setCacheList("work:node:gateway", loadNodeList);
CountDownLatch countDownLatch = new CountDownLatch(3000);
new Thread(() -> {
for (int i = 0; i < 1000; i++) {
Long cursor = redisService.increment("cursor", 1L);
String nodeId = redisService.getCacheListValue("work:node:gateway", cursor % 100);
System.out.println(Thread.currentThread().getName() + "" + cursor + "-----" + nodeId);
stiNode.sti(nodeId);
countDownLatch.countDown();
}
}).start();
new Thread(() -> {
for (int i = 0; i < 1000; i++) {
Long cursor = redisService.increment("cursor", 1L);
String nodeId = redisService.getCacheListValue("work:node:gateway", cursor % 100);
System.out.println(Thread.currentThread().getName() + "" + cursor + "-----" + nodeId);
stiNode.sti(nodeId);
countDownLatch.countDown();
}
}).start();
new Thread(() -> {
for (int i = 0; i < 1000; i++) {
Long cursor = redisService.increment("cursor", 1L);
String nodeId = redisService.getCacheListValue("work:node:gateway", cursor % 100);
System.out.println(Thread.currentThread().getName() + "" + cursor + "-----" + nodeId);
stiNode.sti(nodeId);
countDownLatch.countDown();
}
}).start();
try {
countDownLatch.await();
stiNode.show();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
class stiNode {
private static Map<String, Integer> stiNodeMap = new HashMap<>();
public synchronized static void sti(String nodeId) {
Integer stiCount = stiNodeMap.getOrDefault(nodeId, 0);
stiNodeMap.put(nodeId, stiCount + 1);
}
public static void show() {
stiNodeMap.forEach((key, val) -> {
System.out.println(key + "-----" + val);
});
}
}
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
class WorkGatewayNode {
/**
* ID
*/
private String nodeId;
/**
*
*/
private Integer weight;
}