Commit a0fe2e6f authored by shenjiaqing's avatar shenjiaqing

提交代码

parent 9a24774e
...@@ -38,7 +38,7 @@ allprojects { ...@@ -38,7 +38,7 @@ allprojects {
} }
group = "cn.com.duiba.boot" group = "cn.com.duiba.boot"
version = "0.0.41-jyy-SNAPSHOT" version = "0.0.60-sjq-SNAPSHOT"
} }
subprojects { subprojects {
...@@ -87,6 +87,10 @@ subprojects { ...@@ -87,6 +87,10 @@ subprojects {
//log4j fix //log4j fix
dependency('org.apache.logging.log4j:log4j-api:2.16.0') dependency('org.apache.logging.log4j:log4j-api:2.16.0')
dependency('org.apache.logging.log4j:log4j-core:2.16.0') dependency('org.apache.logging.log4j:log4j-core:2.16.0')
dependency('cn.hutool:hutool-all:4.1.19')
dependency 'org.aspectj:aspectjtools:1.9.5'
dependency 'org.aspectj:aspectjweaver:1.9.5'
} }
} }
......
...@@ -3,4 +3,5 @@ include 'spring-boot-starter-dsp-model' ...@@ -3,4 +3,5 @@ include 'spring-boot-starter-dsp-model'
include 'spring-boot-starter-dsp-sampler' include 'spring-boot-starter-dsp-sampler'
include 'spring-boot-starter-dsp-warmup' include 'spring-boot-starter-dsp-warmup'
include 'spring-boot-starter-dsp-util' include 'spring-boot-starter-dsp-util'
include 'spring-boot-starter-dsp-rateLimiter'
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile "org.springframework.boot:spring-boot-starter-web"
compile 'org.springframework.boot:spring-boot-autoconfigure'
compile "org.apache.dubbo:dubbo-spring-boot-starter"
compile 'org.aspectj:aspectjtools'
compile 'org.aspectj:aspectjweaver'
compile "cn.com.duiba.boot:spring-boot-starter-redis"
compile("redis.clients:jedis")
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
}
package cn.com.duiba.spring.boot.starter.dsp.rateLimiter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
@Configuration
public class Commons {
@Bean
public DefaultRedisScript<Long> redisLuaScript() {
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
//读取 lua 脚本
redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("limit.lua")));
redisScript.setResultType(Long.class);
return redisScript;
}
}
package cn.com.duiba.spring.boot.starter.dsp.rateLimiter;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
@Activate(group = {CommonConstants.CONSUMER})
public class DubboRpcRateLimitFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
return invoker.invoke(invocation);
}
}
package cn.com.duiba.spring.boot.starter.dsp.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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
@Aspect
@Component
public class LimitAspect {
private static final Logger logger = LoggerFactory.getLogger(LimitAspect.class);
@Resource(name = "redis03StringRedisTemplate")
private StringRedisTemplate stringRedisTemplate;
@Autowired
private DefaultRedisScript<Long> redisLuaScript;
@Autowired
private RateLimitProperties rateLimitProperties;
@Pointcut(value = "@annotation(cn.com.duiba.spring.boot.starter.dsp.rateLimiter.RateLimit)")
public void rateLimitPointcut() {
// 点击注解切入.
}
@Around(value = "rateLimitPointcut()")
public Object interceptor(ProceedingJoinPoint joinPoint) throws Throwable {
if (!rateLimitProperties.isAdxRateLimitSwitch()) {
return joinPoint.proceed();
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Class<?> targetClass = method.getDeclaringClass();
RateLimit rateLimit = method.getAnnotation(RateLimit.class);
if (rateLimit == null) {
return joinPoint.proceed();
}
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String ipAddress = getIpAddress(request);
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(ipAddress).append("-")
.append(targetClass.getName()).append("-")
.append(method.getName()).append("-")
.append(rateLimit.key());
logger.info("限流啦, redis key{}", stringBuffer.toString());
List<String> keys = Collections.singletonList(stringBuffer.toString());
Long number = stringRedisTemplate.execute(redisLuaScript, keys, String.valueOf(rateLimit.count()), String.valueOf(rateLimit.time()));
if (number != null && number != 0 && number <= rateLimit.count()) {
logger.info("限流时间段内访问第:{} 次", number);
return joinPoint.proceed();
}
//由于本文没有配置公共异常类,如果配置可替换
throw new RuntimeException("已经到设置限流次数");
}
private static String getIpAddress(HttpServletRequest request) {
String ipAddress;
try {
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();
}
// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
// = 15
if (ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
}
} catch (Exception e) {
ipAddress = "";
}
return ipAddress;
}
}
package cn.com.duiba.spring.boot.starter.dsp.rateLimiter;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimit {
String key() default "limit";
int time() default 5;
int count() default 5;
}
package cn.com.duiba.spring.boot.starter.dsp.rateLimiter;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
@Component
@RefreshScope
public class RateLimitProperties {
@Getter
@Value("${adx.rate.limit.switch:false}")
private boolean adxRateLimitSwitch;
}
dubboRpcRateLimitFilter=cn.com.duiba.spring.boot.starter.dsp.rateLimiter.DubboRpcRateLimitFilter
\ No newline at end of file
local key = "rate.limit:" .. KEYS[1] --限流KEY
local limit = tonumber(ARGV[1]) --限流大小
local current = tonumber(redis.call('get', key) or "0")
if current + 1 > limit then --如果超出限流大小
return 0
else --请求数+1,并设置2秒过期
redis.call("INCRBY", key,"1")
redis.call("expire", key,"2")
return current + 1
end
...@@ -3,7 +3,6 @@ package cn.com.duiba.spring.boot.starter.dsp.sampler; ...@@ -3,7 +3,6 @@ package cn.com.duiba.spring.boot.starter.dsp.sampler;
import cn.com.duiba.spring.boot.starter.dsp.sampler.converter.ApolloPanGuConverter; import cn.com.duiba.spring.boot.starter.dsp.sampler.converter.ApolloPanGuConverter;
import cn.com.duiba.spring.boot.starter.dsp.sampler.converter.SamplerLogConverter; import cn.com.duiba.spring.boot.starter.dsp.sampler.converter.SamplerLogConverter;
import cn.com.duiba.spring.boot.starter.dsp.sampler.feign.SamplerLogRequestInterceptor; import cn.com.duiba.spring.boot.starter.dsp.sampler.feign.SamplerLogRequestInterceptor;
import cn.com.duiba.spring.boot.starter.dsp.sampler.filter.DubboLogSamplerContextFilter;
import cn.com.duiba.spring.boot.starter.dsp.sampler.filter.RpcLogSamplerContextFilter; import cn.com.duiba.spring.boot.starter.dsp.sampler.filter.RpcLogSamplerContextFilter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
......
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