forked from github/dataease
Merge pull request #10977 from dataease/pr@dev-v2@feat_traffic
feat: 增加api限流机制
This commit is contained in:
commit
b5b34e5052
2
de-xpack
2
de-xpack
@ -1 +1 @@
|
||||
Subproject commit d5537b40bc950fe703b3b726762b34b3f1f57474
|
||||
Subproject commit 839f7d618a87a336fa4cbddb3dbe5d589b24e54b
|
12
sdk/common/src/main/java/io/dataease/traffic/DeTraffic.java
Normal file
12
sdk/common/src/main/java/io/dataease/traffic/DeTraffic.java
Normal file
@ -0,0 +1,12 @@
|
||||
package io.dataease.traffic;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface DeTraffic {
|
||||
int value() default 2;
|
||||
|
||||
String api();
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package io.dataease.traffic;
|
||||
|
||||
import io.dataease.exception.DEException;
|
||||
import io.dataease.traffic.dao.entity.CoreApiTraffic;
|
||||
import io.dataease.traffic.dao.mapper.CoreApiTrafficMapper;
|
||||
import io.dataease.utils.IDUtils;
|
||||
import io.dataease.utils.LogUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
public class DeTrafficAop {
|
||||
|
||||
@Resource
|
||||
private CoreApiTrafficMapper coreApiTrafficMapper;
|
||||
|
||||
final private static String errorMsg = "当前API【%s】设定并发阈值为【%s】,现已经达到限流阈值,请稍后再试!";
|
||||
|
||||
@Around(value = "@annotation(io.dataease.traffic.DeTraffic)")
|
||||
public Object trafficAround(ProceedingJoinPoint point) throws Throwable {
|
||||
MethodSignature ms = (MethodSignature) point.getSignature();
|
||||
Method method = ms.getMethod();
|
||||
DeTraffic traffic = method.getAnnotation(DeTraffic.class);
|
||||
int value = traffic.value();
|
||||
String api = traffic.api();
|
||||
Object result = null;
|
||||
try {
|
||||
Integer count = coreApiTrafficMapper.apiCount(api);
|
||||
if (count == 0) {
|
||||
CoreApiTraffic apiTraffic = new CoreApiTraffic();
|
||||
apiTraffic.setId(IDUtils.snowID());
|
||||
apiTraffic.setAlive(1);
|
||||
apiTraffic.setThreshold(value);
|
||||
apiTraffic.setApi(api);
|
||||
coreApiTrafficMapper.insert(apiTraffic);
|
||||
result = point.proceed();
|
||||
return result;
|
||||
}
|
||||
int alive = coreApiTrafficMapper.getAlive(api);
|
||||
if (alive < value) {
|
||||
coreApiTrafficMapper.upgrade(api);
|
||||
result = point.proceed();
|
||||
return result;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
} finally {
|
||||
if (ObjectUtils.isNotEmpty(result)) {
|
||||
coreApiTrafficMapper.releaseAlive(api);
|
||||
}
|
||||
}
|
||||
DEException.throwException(errorMsg);
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package io.dataease.traffic.dao.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
@TableName("core_api_traffic")
|
||||
@Data
|
||||
public class CoreApiTraffic implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -9130425144350145905L;
|
||||
|
||||
private Long id;
|
||||
|
||||
private String api;
|
||||
|
||||
private Integer threshold;
|
||||
|
||||
private Integer alive;
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package io.dataease.traffic.dao.mapper;
|
||||
|
||||
import io.dataease.traffic.dao.entity.CoreApiTraffic;
|
||||
import org.apache.ibatis.annotations.*;
|
||||
|
||||
@Mapper
|
||||
public interface CoreApiTrafficMapper {
|
||||
|
||||
@Select("select `alive` from `core_api_traffic` where `api` = #{api}")
|
||||
int getAlive(@Param("api") String api);
|
||||
|
||||
@Update("update `core_api_traffic` set alive = alive + 1 where `api` = #{api}")
|
||||
void upgrade(@Param("api") String api);
|
||||
|
||||
@Insert("insert into core_api_traffic values(#{id}, #{api}, #{threshold}, 0)")
|
||||
void insert(CoreApiTraffic traffic);
|
||||
|
||||
@Select("select count(*) from core_api_traffic where api = #{api}")
|
||||
Integer apiCount(@Param("api") String api);
|
||||
|
||||
@Update("""
|
||||
update `core_api_traffic` set alive =
|
||||
CASE WHEN alive > 0 THEN alive - 1
|
||||
ELSE alive END
|
||||
where `api` = #{api}
|
||||
""")
|
||||
void releaseAlive(@Param("api") String api);
|
||||
|
||||
@Delete("delete from core_api_traffic")
|
||||
void cleanTraffic();
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package io.dataease.traffic.starter;
|
||||
|
||||
import io.dataease.traffic.dao.mapper.CoreApiTrafficMapper;
|
||||
import io.dataease.utils.LogUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class DeTrafficStarter implements ApplicationRunner {
|
||||
|
||||
@Resource
|
||||
private CoreApiTrafficMapper coreApiTrafficMapper;
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
try {
|
||||
coreApiTrafficMapper.cleanTraffic();
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), new Throwable(e));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user