Commit f4066961 authored by xieshaojun's avatar xieshaojun

api限制配置问题

parent 20b7d9fc
...@@ -144,11 +144,9 @@ ...@@ -144,11 +144,9 @@
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId> <artifactId>spring-test</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>cn.yueshutong</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-current-limiting</artifactId> <artifactId>spring-boot-starter-aop</artifactId>
<version>0.0.1.RELEASE</version>
</dependency> </dependency>
</dependencies> </dependencies>
......
package vc.thinker.config.interceptor;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.RateLimiter;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import vc.thinker.exception.CurrentLimitException;
import vc.thinker.utils.IpUtils;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* @author : xieshaojun
* @date : 2023/1/5 10:32
*/
@Order(1)
@Aspect
@Configuration
public class LimitAspect {
@Autowired(required = false)
HttpServletRequest request;
@Autowired
private LimitConfig limitConfig;
@Autowired
private LoadingCache<String, RateLimiter> caches;
@Bean
public LoadingCache<String, RateLimiter> loadingCache() {
LoadingCache<String, RateLimiter> caches = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(1, TimeUnit.DAYS)
.build(new CacheLoader<>() {
@Override
public RateLimiter load(String s) {
if (ObjectUtils.isEmpty(limitConfig.getSecondLimit())) {
return RateLimiter.create(1);
}else {
return RateLimiter.create(limitConfig.getSecondLimit());
}
}
});
return caches;
}
@Pointcut("@annotation(vc.thinker.config.interceptor.ServiceLimit)")
public void serviceAspect(){
}
@Around("serviceAspect()")
public Object around(ProceedingJoinPoint joinPoint){
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
Method method = signature.getMethod();
ServiceLimit serviceLimit = method.getAnnotation(ServiceLimit.class);
ServiceLimit.LimitType limitType = serviceLimit.limitType();
String key = serviceLimit.key();
Object object;
try {
if (Objects.equals(limitType,ServiceLimit.LimitType.IP)){
key = IpUtils.getIpAddr(request);
}
RateLimiter rateLimiter = caches.get(key);
boolean acquire = rateLimiter.tryAcquire();
if (acquire){
object = joinPoint.proceed();
}else {
throw new CurrentLimitException("请求太频繁");
}
}catch (Throwable e){
throw new CurrentLimitException("请求太频繁");
}
return object;
}
}
package vc.thinker.config.interceptor;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author : xieshaojun
* @date : 2023/1/5 11:01
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "api-limit")
public class LimitConfig {
private double secondLimit;
}
package vc.thinker.config.interceptor;
import java.lang.annotation.*;
/**
* @author : xieshaojun
* @date : 2023/1/5 10:28
*/
@Target({ElementType.PARAMETER,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ServiceLimit {
String message() default "";
String key() default "";
LimitType limitType() default LimitType.CUSTOMER;
/**
* 类型
*/
enum LimitType{
// 自定义
CUSTOMER,
// ip
IP,
;
}
}
...@@ -18,7 +18,7 @@ public class CurrentLimitException extends RuntimeException { ...@@ -18,7 +18,7 @@ public class CurrentLimitException extends RuntimeException {
public CurrentLimitException(String message) { public CurrentLimitException(String message) {
super(message); super(message);
this.code = "500"; this.code = "429";
} }
public CurrentLimitException(String message, String code) { public CurrentLimitException(String message, String code) {
......
package vc.thinker.exception;
import cn.yueshutong.springbootstartercurrentlimiting.annotation.CurrentLimiter;
import cn.yueshutong.springbootstartercurrentlimiting.handler.CurrentAspectHandler;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;
/**
* @author : xieshaojun
* @date : 2023/1/4 18:13
*/
@Component
public class CurrentLimitHandler implements CurrentAspectHandler {
@Override
public Object around(ProceedingJoinPoint pjp, CurrentLimiter rateLimiter) {
//限流的返回数据可以自己根据需求场景设计
throw new CurrentLimitException("接口访问繁忙,休息一下");
}
}
\ No newline at end of file
package vc.thinker.utils;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* @author YanZhuoMin
* @since 2020/4/22
*/
public class IpUtils {
private IpUtils() {
}
/**
* 获取当前网络ip
* @param request
* @return
*/
public static String getIpAddr(HttpServletRequest request){
String ipAddress = request.getHeader("x-forwarded-for");
if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){
//根据网卡取本机配置的IP
InetAddress inet=null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
ipAddress= inet.getHostAddress();
}
}
//对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15
if(ipAddress.indexOf(",")>0){
ipAddress = ipAddress.substring(0,ipAddress.indexOf(","));
}
}
return ipAddress;
}
/**
* 获得MAC地址
* @param ip
* @return
*/
public static String getMACAddress(String ip){
String str = "";
String macAddress = "";
try {
Process p = Runtime.getRuntime().exec("nbtstat -A " + ip);
InputStreamReader ir = new InputStreamReader(p.getInputStream());
LineNumberReader input = new LineNumberReader(ir);
for (int i = 1; i < 100; i++) {
str = input.readLine();
if (str != null) {
if (str.indexOf("MAC Address") > 1) {
macAddress = str.substring(str.indexOf("MAC Address") + 14, str.length());
break;
}
}
}
} catch (IOException e) {
e.printStackTrace(System.out);
}
return macAddress;
}
}
package vc.thinker.web; package vc.thinker.web;
import cn.yueshutong.springbootstartercurrentlimiting.annotation.CurrentLimiter;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import vc.thinker.config.interceptor.ServiceLimit;
import vc.thinker.response.SimpleResponse; import vc.thinker.response.SimpleResponse;
import vc.thinker.thirdpartyproxy.ProtocolType; import vc.thinker.thirdpartyproxy.ProtocolType;
import vc.thinker.thirdpartyproxy.protocolimpls.centralAir.CentralAirProtocol; import vc.thinker.thirdpartyproxy.protocolimpls.centralAir.CentralAirProtocol;
...@@ -35,7 +38,7 @@ public class CentralAirController { ...@@ -35,7 +38,7 @@ public class CentralAirController {
@ApiOperation("设备数据上报接口") @ApiOperation("设备数据上报接口")
@PostMapping("data-report") @PostMapping("data-report")
@CurrentLimiter(QPS = 1) @ServiceLimit(key = "data-report")
public SimpleResponse dataReport(@RequestBody @Valid TerminalDataReportVO reportVO) { public SimpleResponse dataReport(@RequestBody @Valid TerminalDataReportVO reportVO) {
SimpleResponse simpleResponse = new SimpleResponse(); SimpleResponse simpleResponse = new SimpleResponse();
simpleResponse.setCode("200"); simpleResponse.setCode("200");
......
...@@ -36,16 +36,6 @@ mqtt: ...@@ -36,16 +36,6 @@ mqtt:
device: device:
code: zykt-test1 code: zykt-test1
# 接口限制 api-limit:
current: # 每秒最多请求多少次
limiting: secondLimit: 0.1
#开启全局限流 \ No newline at end of file
enabled: false
#开启注解限流,可使注解失效
part-enabled: true
#每秒并发量 这里的qps是全局限流开启的时候的值,如果使用注解在注解里设置QPS值
qps: 1
#开启快速失败,可切换为阻塞
fail-fast: true
#系统启动保护时间为0
initial-delay: 0
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment