refactor: 重构项目结构并添加新功能
- 移除了 SpringCloud/GateWay 模块的全部内容 - 新增 ForJdk17 模块,包含多个子包和类文件 - 更新 pom.xml 文件,添加 slf4j 依赖 - 删除 sdoih.bpmn 文件 Changes application.properties bootstrap.yml GateWayApplication.java GateWayApplicationTests.java K8s查询串行.java LeetCode12.java LeetCode167.java LeetCode718_1.java pom.xml pom.xml sdoih.bpmn Tencent.java 导入CVM集群_CVM接口Reset限频_改为获取窗口再逐渐请求避免限制频率.java 导入容器集群_请求连接超时导致报错_采用异步中间状态处理方式先异步响应.java 请求域名兜底策略_DNS获取IP操作改成从Polaris.java
This commit is contained in:
parent
93ae3a0720
commit
14973b69dd
@ -0,0 +1,41 @@
|
|||||||
|
package cn.whaifree.redo.redo_all_241016;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @version 1.0
|
||||||
|
* @Author whai文海
|
||||||
|
* @Date 2024/10/16 12:10
|
||||||
|
* @注释
|
||||||
|
*/
|
||||||
|
public class LeetCode12 {
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
|
||||||
|
int num = 1994;
|
||||||
|
String result = new Solution().intToRoman(num);
|
||||||
|
System.out.println(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Solution {
|
||||||
|
// 3999
|
||||||
|
static int[] nums = new int[]{1000, 900, 500, 400, 100, 90,50, 40, 10, 9, 5, 4, 1};
|
||||||
|
static String[] strs = new String[]{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
|
||||||
|
public String intToRoman(int num) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (num != 0) {
|
||||||
|
for (int i = 0; i < nums.length; i++) {
|
||||||
|
if (nums[i] <= num) {
|
||||||
|
sb.append(strs[i]);
|
||||||
|
num -= nums[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package cn.whaifree.redo.redo_all_241016;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @version 1.0
|
||||||
|
* @Author whai文海
|
||||||
|
* @Date 2024/11/18 12:14
|
||||||
|
* @注释
|
||||||
|
*/
|
||||||
|
public class LeetCode167 {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
int[] nums = new int[]{2, 7, 11, 15};
|
||||||
|
int target = 9;
|
||||||
|
int[] ints = new Solution().twoSum(nums, target);
|
||||||
|
for (int anInt : ints) {
|
||||||
|
System.out.println(anInt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Solution {
|
||||||
|
public int[] twoSum(int[] numbers, int target) {
|
||||||
|
for (int i = 0; i < numbers.length; i++) {
|
||||||
|
int search = binarySearch(numbers, i + 1, numbers.length - 1, target - numbers[i]);
|
||||||
|
if (search != -1) {
|
||||||
|
return new int[]{i + 1, search + 1};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new int[]{};
|
||||||
|
}
|
||||||
|
|
||||||
|
public int binarySearch(int[] nums, int left, int right, int target) {
|
||||||
|
while (left <= right) {
|
||||||
|
int mid = (left + right) / 2;
|
||||||
|
if (nums[mid] == target) {
|
||||||
|
return mid;
|
||||||
|
}else if (nums[mid] < target) {
|
||||||
|
left = mid + 1;
|
||||||
|
}else {
|
||||||
|
right = mid - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package cn.whaifree.redo.redo_all_241016;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @version 1.0
|
||||||
|
* @Author whai文海
|
||||||
|
* @Date 2024/11/17 19:49
|
||||||
|
* @注释
|
||||||
|
*/
|
||||||
|
public class LeetCode718_1 {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
System.out.println(
|
||||||
|
new Solution()
|
||||||
|
.findLength(
|
||||||
|
new int[]{1, 2, 3, 2, 1, 5, 8, 9},
|
||||||
|
new int[]{3, 2, 1, 5, 8, 4, 7}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
class Solution {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 0-i 0-j 最长的公共字数组的长度 , 必须连续
|
||||||
|
* 1 2 3 2 1 7
|
||||||
|
* 3 0 0 1 0 0 0
|
||||||
|
* 2 0 1 0 2 0 0 if == math,max(i-1 j-1 +1 ) else
|
||||||
|
* 1 1 0 0 0 3 0
|
||||||
|
* 4 0
|
||||||
|
* 7
|
||||||
|
*
|
||||||
|
* @param nums1
|
||||||
|
* @param nums2
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int findLength(int[] nums1, int[] nums2) {
|
||||||
|
int[][] dp = new int[nums1.length + 1][nums2.length + 1];
|
||||||
|
int max = 0;
|
||||||
|
for (int i = 1; i <= nums1.length; i++) {
|
||||||
|
for (int j = 1; j <= nums2.length; j++) {
|
||||||
|
if (nums1[i - 1] == nums2[j - 1]) {
|
||||||
|
dp[i][j] = dp[i - 1][j - 1] + 1;
|
||||||
|
max = Math.max(max, dp[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
186
ForJdk17/src/main/java/cn/whaifree/tmp/project/K8s查询串行.java
Normal file
186
ForJdk17/src/main/java/cn/whaifree/tmp/project/K8s查询串行.java
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
package cn.whaifree.tmp.project;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.RandomUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @version 1.0
|
||||||
|
* @Author whai文海
|
||||||
|
* @Date 2024/11/17 14:24
|
||||||
|
* @注释
|
||||||
|
*/
|
||||||
|
interface TimeInterface {
|
||||||
|
Instance k8sDescribe(Integer instanceId) throws InterruptedException;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class K8s查询串行 {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void K8s查询串行改并行() throws Exception {
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
System.out.println("=================开始时间:" + start);
|
||||||
|
List<Integer> instanceIds = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
|
||||||
|
List<Instance> instances = K8s查询串行.describeInstance(instanceIds);
|
||||||
|
System.out.println(instances);
|
||||||
|
long end = System.currentTimeMillis();
|
||||||
|
System.out.println("=================结束时间:" + end);
|
||||||
|
log.info("耗时:" + (end - start));
|
||||||
|
|
||||||
|
// List<Instance> instances = o.describeInstance(instanceIds);
|
||||||
|
// System.out.println(instances);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static TimeInterface k8sProxy = null;
|
||||||
|
static {
|
||||||
|
Object o= Proxy.newProxyInstance(TimeInterface.class.getClassLoader(), new Class[]{TimeInterface.class},
|
||||||
|
(proxy, method, args) -> {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
Object invoke = method.invoke(new K8sServer(), args);
|
||||||
|
long end = System.currentTimeMillis();
|
||||||
|
log.info("当前时间{},耗时:{}", new Date(end), end - start);
|
||||||
|
return invoke;
|
||||||
|
});
|
||||||
|
k8sProxy = (TimeInterface) o;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Instance> describeInstance(List<Integer> instanceIds) throws InterruptedException {
|
||||||
|
List<Instance> instances = new ArrayList<>();
|
||||||
|
for (Integer instanceId : instanceIds) {
|
||||||
|
Instance instance = k8sProxy.k8sDescribe(instanceId);
|
||||||
|
System.out.println(StrUtil.format("instanceId:{},instanceInfo:{}", instanceId, instance.getInstanceInfo()));
|
||||||
|
instances.add(instance);
|
||||||
|
}
|
||||||
|
return instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class K8sServer implements TimeInterface{
|
||||||
|
static Map<Integer, Instance> map = new HashMap<>();
|
||||||
|
static {
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
map.put(i, new Instance(i,
|
||||||
|
StrUtil.format(
|
||||||
|
"{instanceId:{},memoryUse:{},cpuUse:{}}", i, "80%", "90%")));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public Instance k8sDescribe(Integer instanceId) throws InterruptedException {
|
||||||
|
Thread.sleep(RandomUtil.randomInt(500, 1100));
|
||||||
|
return map.get(instanceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
class Instance {
|
||||||
|
Integer instaceId;
|
||||||
|
String instanceInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
class K8s查询并行 {
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
System.out.println("=================开始时间:" + start);
|
||||||
|
List<Integer> instanceIds = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
|
||||||
|
List<Instance> instances = K8s查询并行.describeInstance2(instanceIds);
|
||||||
|
System.out.println(instances);
|
||||||
|
long end = System.currentTimeMillis();
|
||||||
|
System.out.println("=================结束时间:" + end);
|
||||||
|
log.info("耗时:" + (end - start));
|
||||||
|
|
||||||
|
// List<Instance> instances = o.describeInstance(instanceIds);
|
||||||
|
// System.out.println(instances);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static TimeInterface k8sProxy = null;
|
||||||
|
static ExecutorService executor = null;
|
||||||
|
static {
|
||||||
|
Object o= Proxy.newProxyInstance(TimeInterface.class.getClassLoader(), new Class[]{TimeInterface.class},
|
||||||
|
(proxy, method, args) -> {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
Object invoke = method.invoke(new K8sServer(), args);
|
||||||
|
long end = System.currentTimeMillis();
|
||||||
|
log.info("当前时间{},耗时:{}", new Date(end), end - start);
|
||||||
|
return invoke;
|
||||||
|
});
|
||||||
|
k8sProxy = (TimeInterface) o;
|
||||||
|
executor = Executors.newFixedThreadPool(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Instance> describeInstance(List<Integer> instanceIds) throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
|
List<Instance> instances = new ArrayList<>();
|
||||||
|
|
||||||
|
List<Future<Instance>> futures = new ArrayList<>();
|
||||||
|
for (Integer instanceId : instanceIds) {
|
||||||
|
Future<Instance> submit = executor.submit(() -> k8sProxy.k8sDescribe(instanceId));
|
||||||
|
futures.add(submit);
|
||||||
|
}
|
||||||
|
for (Future<Instance> future : futures) {
|
||||||
|
instances.add(future.get(10, TimeUnit.SECONDS));
|
||||||
|
}
|
||||||
|
return instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Instance> describeInstance2(List<Integer> instanceIds) throws InterruptedException, ExecutionException {
|
||||||
|
List<Instance> instances = new ArrayList<>();
|
||||||
|
|
||||||
|
int size = instanceIds.size();
|
||||||
|
CountDownLatch latch = new CountDownLatch(size);
|
||||||
|
for (Integer instanceId : instanceIds) {
|
||||||
|
executor.submit(new MyCallable(latch, instanceId, instances));
|
||||||
|
}
|
||||||
|
latch.await(10, TimeUnit.SECONDS);
|
||||||
|
return instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class MyCallable implements Callable<Instance> {
|
||||||
|
|
||||||
|
CountDownLatch latch;
|
||||||
|
Integer instanceId;
|
||||||
|
List<Instance> instances;
|
||||||
|
|
||||||
|
|
||||||
|
public MyCallable(CountDownLatch latch, Integer instanceId, List<Instance> instances) {
|
||||||
|
this.latch = latch;
|
||||||
|
this.instanceId = instanceId;
|
||||||
|
this.instances = instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Instance call() throws Exception {
|
||||||
|
try {
|
||||||
|
Instance instance = k8sProxy.k8sDescribe(instanceId);
|
||||||
|
instances.add(instance);
|
||||||
|
return instance;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}finally {
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
69
ForJdk17/src/main/java/cn/whaifree/tmp/project/Tencent.java
Normal file
69
ForJdk17/src/main/java/cn/whaifree/tmp/project/Tencent.java
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package cn.whaifree.tmp.project;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.RandomUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @version 1.0
|
||||||
|
* @Author whai文海
|
||||||
|
* @Date 2024/11/17 11:07
|
||||||
|
* @注释
|
||||||
|
*/
|
||||||
|
public class Tencent {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(Tencent.class);
|
||||||
|
|
||||||
|
/* 以 Consul 配置中心为基础,开发出预分配、上限资源分配接口,成功让运营端控制分配的tsf-agent资
|
||||||
|
源与租户端默认值实现同步。*/
|
||||||
|
|
||||||
|
/*当实例或集群规模扩大时,Pod相关数据查询调用K8sAPI会显著延迟,平均时延高达15秒。采用多线程
|
||||||
|
处理策略,提升了接口的并发处理能力,成功地将在40个Pod上查询时延从大约15秒降低至3秒内,显著
|
||||||
|
提升用户体验。*/
|
||||||
|
/*实施请求域名兜底策略,把请求通过 DNS 获取 IP 的操作迁移至 Polaris 北极星注册中心,同时将
|
||||||
|
Consul 配置设定为兜底策略,以此保障请求在不同场景下都能顺利进行,提升系统的稳定性和可靠性。*/
|
||||||
|
|
||||||
|
/*申请对 CVM 服务器的重置接口限频进行处理,一旦超过限频则响应报错,通过获取窗口大小分片的方
|
||||||
|
式来解决 CVM 重置接口限频的问题,及时响应至前端。*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
导入容器到集群时,下游处理时间过长无法及时响应导致断开,
|
||||||
|
- 异步
|
||||||
|
- 超时再异步 10s超时候先返回临时响应 ,数据不一致
|
||||||
|
- 超时候
|
||||||
|
- 超时再异步 10s超时候先返回临时响应 ,提供接口对结果进行查询
|
||||||
|
|
||||||
|
申请对 CVM 服务器的重置接口限频进行处理,一旦超过限频则响应报错,通过获取窗口大小分片的方
|
||||||
|
式来解决 CVM 重置接口限频的问题,及时响应至前端。*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Consul开发预分配上下限资源接口{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class 请求域名兜底策略_DNS获取IP操作改成从Polaris{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,143 @@
|
|||||||
|
package cn.whaifree.tmp.project;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @version 1.0
|
||||||
|
* @Author whai文海
|
||||||
|
* @Date 2024/11/17 18:09
|
||||||
|
* @注释
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class 导入CVM集群_CVM接口Reset限频_改为获取窗口再逐渐请求避免限制频率 {
|
||||||
|
|
||||||
|
|
||||||
|
public static void originMethod(List<String> instanceIds) {
|
||||||
|
/**
|
||||||
|
* 不限制
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
for (String instanceId : instanceIds) {
|
||||||
|
boolean reset = MasterAPI.reset(instanceId);
|
||||||
|
if (!reset) {
|
||||||
|
throw new RuntimeException("RateLimit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("RateLimit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static List<Integer> advanceMethod(List<String> instanceIds) throws InterruptedException {
|
||||||
|
List<Integer> result = new ArrayList<>();
|
||||||
|
int rateLimit = RateLimiterExecutor.rateLimit;// 从配置中心获取
|
||||||
|
for (int i = 0; i < instanceIds.size(); i += rateLimit) {
|
||||||
|
int end = i + rateLimit;
|
||||||
|
if (end > instanceIds.size()) {
|
||||||
|
end = instanceIds.size();
|
||||||
|
}
|
||||||
|
List<String> subList = instanceIds.subList(i, end);
|
||||||
|
|
||||||
|
while (!MasterAPI.reset(subList)) {
|
||||||
|
log.info("{} RateLimit Retry After 500ms", Thread.currentThread().getName());
|
||||||
|
Thread.sleep(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
|
||||||
|
List<String> instanceIds = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
instanceIds.add("i-" + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
originMethod(instanceIds);
|
||||||
|
|
||||||
|
Thread.sleep(1000);
|
||||||
|
|
||||||
|
System.out.println("=====================================");
|
||||||
|
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
advanceMethod(instanceIds);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
advanceMethod(instanceIds);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
class MasterAPI{
|
||||||
|
|
||||||
|
public static boolean reset(List<String> instanceIds) {
|
||||||
|
for (String instanceId : instanceIds) {
|
||||||
|
boolean reset = reset(instanceId);
|
||||||
|
if (!reset) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public static boolean reset(String instanceId) {
|
||||||
|
// 限频模拟
|
||||||
|
if (RateLimiterExecutor.allowRequest()) {
|
||||||
|
log.info(StrUtil.format("reset: {}", instanceId));
|
||||||
|
return true;
|
||||||
|
}else {
|
||||||
|
log.error(StrUtil.format("reset: {} RateLimit !!!!!", instanceId));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RateLimiterExecutor{
|
||||||
|
static AtomicInteger times = new AtomicInteger(0); // 次数
|
||||||
|
static long startTime = 0; // 开始时间
|
||||||
|
static int rateLimit = 10; // 限流频率,1秒允许多少次
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否允许请求
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean allowRequest() {
|
||||||
|
if (times.get() == 0) {
|
||||||
|
// 开始计数
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
// 1000 为窗口大小
|
||||||
|
if (System.currentTimeMillis() - startTime > 1000) {
|
||||||
|
// 超过1秒,重新统计窗口
|
||||||
|
times.set(0);
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
int i = times.incrementAndGet();
|
||||||
|
// 触发限频,重新统计窗口
|
||||||
|
return i <= rateLimit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,118 @@
|
|||||||
|
package cn.whaifree.tmp.project;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
|
import cn.hutool.core.util.RandomUtil;
|
||||||
|
import cn.whaifree.leetCode.utils.MapUtils;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @version 1.0
|
||||||
|
* @Author whai文海
|
||||||
|
* @Date 2024/11/18 14:07
|
||||||
|
* @注释
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class 导入容器集群_请求连接超时导致报错_采用异步中间状态处理方式先异步响应 {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() throws ExecutionException, InterruptedException, TimeoutException {
|
||||||
|
List<Integer> instanceId = Lists.newArrayList();
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
instanceId.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map map = PaaS.requestAdvance(instanceId);
|
||||||
|
System.out.println(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
class K8sServer{
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public static Map<String, List<Integer>> addToCluster(List<Integer> instanceId) {
|
||||||
|
Map<String, List<Integer>> build =
|
||||||
|
MapUtil.builder("", instanceId)
|
||||||
|
.put("success", new ArrayList<>())
|
||||||
|
.put("fail", new ArrayList<>())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
for (int i = 0; i < instanceId.size(); i++) {
|
||||||
|
build.get("success").add(instanceId.get(i));
|
||||||
|
log.info("成功添加实例:{}", instanceId.get(i));
|
||||||
|
// if (RandomUtil.randomInt(1000) % 10 != 0) {
|
||||||
|
// build.get("success").add(instanceId.get(i));
|
||||||
|
// log.info("成功添加实例:{}", instanceId.get(i));
|
||||||
|
// }else {
|
||||||
|
// build.get("fail").add(instanceId.get(i));
|
||||||
|
// log.warn("添加实例失败:{}", instanceId.get(i));
|
||||||
|
// }
|
||||||
|
Thread.sleep(1000);
|
||||||
|
}
|
||||||
|
return build;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Integer> instanceId = Lists.newArrayList();
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
instanceId.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map map = PaaS.requestAdvance(instanceId);
|
||||||
|
System.out.println(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaaS{
|
||||||
|
|
||||||
|
public static Map requestOrigin(List<Integer> instanceId) {
|
||||||
|
CompletableFuture<Map<String, List<Integer>>> future = CompletableFuture.supplyAsync(() -> K8sServer.addToCluster(instanceId));
|
||||||
|
try {
|
||||||
|
return future.get(10, TimeUnit.SECONDS);
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
log.error("请求连接超时");
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ExecutorService executor = Executors.newFixedThreadPool(10);
|
||||||
|
|
||||||
|
public static Map requestAdvance(List<Integer> instanceId) {
|
||||||
|
|
||||||
|
CompletableFuture<Map<String, List<Integer>>> future =
|
||||||
|
CompletableFuture.supplyAsync(
|
||||||
|
() -> K8sServer.addToCluster(instanceId)
|
||||||
|
, executor);
|
||||||
|
|
||||||
|
Map<String, List<Integer>> res = future.orTimeout(10, TimeUnit.SECONDS)
|
||||||
|
.handle((result, ex) -> {
|
||||||
|
if (ex != null) {
|
||||||
|
if (ex instanceof TimeoutException) {
|
||||||
|
log.error("请求连接超时");
|
||||||
|
return null; // 返回null表示临时中间状态,为在处理中
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}).join();
|
||||||
|
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package cn.whaifree.tmp.project;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @version 1.0
|
||||||
|
* @Author whai文海
|
||||||
|
* @Date 2024/11/17 15:38
|
||||||
|
* @注释
|
||||||
|
*/
|
||||||
|
public class 请求域名兜底策略_DNS获取IP操作改成从Polaris{
|
||||||
|
|
||||||
|
/*实施请求域名兜底策略,把请求通过 DNS 获取 IP 的操作迁移至 Polaris 北极星注册中心,同时将
|
||||||
|
Consul 配置设定为兜底策略,以此保障请求在不同场景下都能顺利进行,提升系统的稳定性和可靠性。*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 要求所有的注册中心都往北极星迁移,所以需要在之前的基础上做兼容
|
||||||
|
*/
|
||||||
|
|
||||||
|
//csm风险项暴露,仅通过使用域名调用服务,无法自动容灾,受解析 TTL 影响,容灾切换时间超过10min甚至更长
|
||||||
|
static class GetIp{
|
||||||
|
|
||||||
|
static int retryTime = 10;
|
||||||
|
public String getDomain() {
|
||||||
|
int times = 1;
|
||||||
|
while (times++ < retryTime) {
|
||||||
|
String ip = Polaris.get("dns");
|
||||||
|
if (!ip.isEmpty()) {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 备用Consu接入
|
||||||
|
return Consul.get("dns");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Polaris{
|
||||||
|
|
||||||
|
public static Map<String, String> config = Maps.newHashMap();
|
||||||
|
static {
|
||||||
|
config.put("dns", "Polaris IP");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String get(String key) {
|
||||||
|
return config.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Consul{
|
||||||
|
|
||||||
|
public static Map<String, String> config = Maps.newHashMap();
|
||||||
|
static {
|
||||||
|
config.put("dns", "Consul IP");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String get(String key) {
|
||||||
|
// 如果获取不到
|
||||||
|
return config.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,171 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<parent>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
|
||||||
<version>3.3.5</version>
|
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
|
||||||
</parent>
|
|
||||||
<groupId>com.whai.springcloud</groupId>
|
|
||||||
<artifactId>GateWay</artifactId>
|
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
|
||||||
<name>GateWay</name>
|
|
||||||
<description>GateWay</description>
|
|
||||||
<url/>
|
|
||||||
<licenses>
|
|
||||||
<license/>
|
|
||||||
</licenses>
|
|
||||||
<developers>
|
|
||||||
<developer/>
|
|
||||||
</developers>
|
|
||||||
<scm>
|
|
||||||
<connection/>
|
|
||||||
<developerConnection/>
|
|
||||||
<tag/>
|
|
||||||
<url/>
|
|
||||||
</scm>
|
|
||||||
<properties>
|
|
||||||
<java.version>17</java.version>
|
|
||||||
<spring-cloud.version>2023.0.3</spring-cloud.version>
|
|
||||||
<swagger.fox.version>3.0.0</swagger.fox.version>
|
|
||||||
|
|
||||||
</properties>
|
|
||||||
<dependencies>
|
|
||||||
|
|
||||||
<!-- SpringCloud Gateway -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-starter-gateway</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- SpringCloud Alibaba Nacos -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.alibaba.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- SpringCloud Alibaba Nacos Config -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.alibaba.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- SpringCloud Alibaba Sentinel -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.alibaba.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- SpringCloud Alibaba Sentinel Gateway -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.alibaba.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Sentinel Datasource Nacos -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.alibaba.csp</groupId>
|
|
||||||
<artifactId>sentinel-datasource-nacos</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Sentinel 实时监控 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.alibaba.csp</groupId>
|
|
||||||
<artifactId>sentinel-transport-simple-http</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- SpringBoot Actuator -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- SpringCloud Loadbalancer -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-loadbalancer</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!--验证码 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>pro.fessional</groupId>
|
|
||||||
<artifactId>kaptcha</artifactId>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>javax.servlet</groupId>
|
|
||||||
<artifactId>javax.servlet-api</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>javax.servlet</groupId>
|
|
||||||
<artifactId>servlet-api</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Swagger -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.springfox</groupId>
|
|
||||||
<artifactId>springfox-swagger-ui</artifactId>
|
|
||||||
<version>${swagger.fox.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.springfox</groupId>
|
|
||||||
<artifactId>springfox-swagger2</artifactId>
|
|
||||||
<version>${swagger.fox.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- knife4j -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.xiaoymin</groupId>
|
|
||||||
<artifactId>knife4j-spring-ui</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.xiaoymin</groupId>
|
|
||||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<finalName>${project.artifactId}</finalName>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>repackage</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
<!-- 为防止打包docker部署读取不到配置文件问题资源文件 -->
|
|
||||||
<resources>
|
|
||||||
<resource>
|
|
||||||
<directory>src/main/java</directory>
|
|
||||||
<includes>
|
|
||||||
<include>**/*.yml</include>
|
|
||||||
<include>**/*.properties</include>
|
|
||||||
<include>**/*.xml</include>
|
|
||||||
</includes>
|
|
||||||
<filtering>false</filtering>
|
|
||||||
</resource>
|
|
||||||
<resource>
|
|
||||||
<directory>src/main/resources</directory>
|
|
||||||
<includes>
|
|
||||||
<include>**/*.yml</include>
|
|
||||||
<include>**/*.properties</include>
|
|
||||||
<include>**/*.xml</include>
|
|
||||||
</includes>
|
|
||||||
<filtering>false</filtering>
|
|
||||||
</resource>
|
|
||||||
</resources>
|
|
||||||
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
|
@ -1,13 +0,0 @@
|
|||||||
package com.whai.springcloud.gateway;
|
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
|
|
||||||
@SpringBootApplication
|
|
||||||
public class GateWayApplication {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
SpringApplication.run(GateWayApplication.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
spring.application.name=GateWay
|
|
@ -1,48 +0,0 @@
|
|||||||
# Tomcat
|
|
||||||
server:
|
|
||||||
port: 6880
|
|
||||||
|
|
||||||
# Spring
|
|
||||||
spring:
|
|
||||||
application:
|
|
||||||
# 应用名称
|
|
||||||
name: whai-gateway
|
|
||||||
cloud:
|
|
||||||
nacos:
|
|
||||||
discovery:
|
|
||||||
# 服务注册地址
|
|
||||||
server-addr: 192.168.50.248:8848
|
|
||||||
username: nacos
|
|
||||||
password: nacos
|
|
||||||
config:
|
|
||||||
# 配置中心地址
|
|
||||||
server-addr: 192.168.50.248:8848
|
|
||||||
username: nacos
|
|
||||||
password: nacos
|
|
||||||
# 配置文件格式
|
|
||||||
file-extension: yml
|
|
||||||
# 共享配置
|
|
||||||
shared-configs:
|
|
||||||
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
|
||||||
# sentinel:
|
|
||||||
# # 取消控制台懒加载
|
|
||||||
# eager: true
|
|
||||||
# transport:
|
|
||||||
# # 配置控制台服务地址
|
|
||||||
# dashboard: 127.0.0.1:8080
|
|
||||||
# # 默认 8719 端口,假如被占用会自动从 8719 开始依次 +1 扫描,直至找到未被占用的端口
|
|
||||||
# port: 8719
|
|
||||||
# # nacos配置持久化
|
|
||||||
# datasource:
|
|
||||||
# ds1:
|
|
||||||
# nacos:
|
|
||||||
# server-addr: 127.0.0.1:8848
|
|
||||||
# dataId: sentinel-pmhub-gateway
|
|
||||||
# groupId: DEFAULT_GROUP
|
|
||||||
# data-type: json
|
|
||||||
# rule-type: gw-flow
|
|
||||||
|
|
||||||
# 实时log配置,可在http://localhost:6888/ 监控中心查看实时日志
|
|
||||||
logging:
|
|
||||||
file:
|
|
||||||
name: logs/${spring.application.name}/info.log
|
|
@ -1,13 +0,0 @@
|
|||||||
package com.whai.springcloud.gateway;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
class GateWayApplicationTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void contextLoads() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
22
pom.xml
22
pom.xml
@ -16,7 +16,29 @@
|
|||||||
<module>SpringDemo</module>
|
<module>SpringDemo</module>
|
||||||
</modules> <!--定义了 Maven 项目的打包方式(比如 jar,war...),默认使用 jar。-->
|
</modules> <!--定义了 Maven 项目的打包方式(比如 jar,war...),默认使用 jar。-->
|
||||||
|
|
||||||
|
<!-- 依赖软件版本 -->
|
||||||
|
<properties>
|
||||||
|
<slf4j.version>1.7.30</slf4j.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>${slf4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>${slf4j.version}</version>
|
||||||
|
<!-- 注意,若无type为jar则报错-->
|
||||||
|
<type>jar</type>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!--hutool-->
|
<!--hutool-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
||||||
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1730813700188" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema"/>
|
|
Loading…
Reference in New Issue
Block a user