Commit da3b426e authored by shenjiaqing's avatar shenjiaqing

提交代码

parent 8c9275ef
...@@ -38,7 +38,7 @@ allprojects { ...@@ -38,7 +38,7 @@ allprojects {
} }
group = "cn.com.duiba.boot" group = "cn.com.duiba.boot"
version = "0.0.63-sjq-SNAPSHOT" version = "0.0.73-sjq-SNAPSHOT"
} }
subprojects { subprojects {
......
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 DubboRateLimitFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
return invoker.invoke(invocation);
}
}
...@@ -11,20 +11,27 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -11,20 +11,27 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component; 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.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
@Aspect @Aspect
@Component @Component
public class LimitAspect { public class LimitAspect {
private static final Logger logger = LoggerFactory.getLogger(LimitAspect.class); private final static Logger logger = LoggerFactory.getLogger(LimitAspect.class);
private final static Map<String, AtomicLong> map = new ConcurrentHashMap<>();
private final static Integer REDIS_NODE_NUM = 4;
static {
map.put("rate.limit:com.duiba.tuia.adx.web.service.algo.impl.AdxAlgoServiceImpl-hello-limit", new AtomicLong());
}
@Resource(name = "redis03StringRedisTemplate") @Resource(name = "redis03StringRedisTemplate")
private StringRedisTemplate stringRedisTemplate; private StringRedisTemplate stringRedisTemplate;
...@@ -55,21 +62,27 @@ public class LimitAspect { ...@@ -55,21 +62,27 @@ public class LimitAspect {
return joinPoint.proceed(); return joinPoint.proceed();
} }
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); StringBuilder stringBuilder = new StringBuilder();
String ipAddress = getIpAddress(request); stringBuilder.append("rate.limit:").
append(targetClass.getName()).append("-")
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(ipAddress).append("-")
.append(targetClass.getName()).append("-")
.append(method.getName()).append("-") .append(method.getName()).append("-")
.append(rateLimit.key()); .append(rateLimit.key());
logger.info("限流啦, redis key{}", stringBuffer.toString());
List<String> keys = Collections.singletonList(stringBuffer.toString()); String s = stringBuilder.toString();
long index = map.get(s).getAndIncrement() % REDIS_NODE_NUM;
String redisKey = s + index;
logger.info("限流啦, redis key{}", redisKey);
List<String> keys = Collections.singletonList(redisKey);
int totalLimitCount = rateLimit.count();
int limitCount = totalLimitCount % REDIS_NODE_NUM > index ? totalLimitCount / REDIS_NODE_NUM + 1 : totalLimitCount / REDIS_NODE_NUM;
Long number = stringRedisTemplate.execute(redisLuaScript, keys, String.valueOf(rateLimit.count()), String.valueOf(rateLimit.time())); Long number = stringRedisTemplate.execute(redisLuaScript, keys, String.valueOf(limitCount), String.valueOf(rateLimit.time()));
if (number != null && number != 0 && number <= rateLimit.count()) { if (number != null && number != 0 && number <= limitCount) {
logger.info("限流时间段内访问第:{} 次", number); logger.info("限流时间段内访问第:{} 次", number);
return joinPoint.proceed(); return joinPoint.proceed();
} }
...@@ -78,31 +91,4 @@ public class LimitAspect { ...@@ -78,31 +91,4 @@ public class LimitAspect {
throw new RuntimeException("已经到设置限流次数"); 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;
}
} }
dubboRateLimitFilter=cn.com.duiba.spring.boot.starter.dsp.rateLimiter.DubboRateLimitFilter
\ No newline at end of file
local key = "rate.limit:" .. KEYS[1] --限流KEY
local limit = tonumber(ARGV[1]) --限流大小 local limit = tonumber(ARGV[1]) --限流大小
local current = tonumber(redis.call('get', key) or "0") local current = tonumber(redis.call('get', KEYS[1]) or "0")
if current + 1 > limit then --如果超出限流大小 if current + 1 > limit then --如果超出限流大小
return 0 return 0
else --请求数+1,并设置2秒过期 else --请求数+1,并设置2秒过期
redis.call("INCRBY", key,"1") redis.call("INCRBY", KEYS[1], "1")
redis.call("expire", key,"2") redis.call("expire", KEYS[1], "2")
return current + 1 return current + 1
end end
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