Authored by hugufei

fix 个性化自动降级

... ... @@ -9,8 +9,8 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoDownGradePersional {
public int timeInSecond();
public int rateLimitInSecond();
public int maxCount();
public int rateLimit();
}
... ...
package com.yoho.search.common.downgrade.persional;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
... ... @@ -14,29 +13,26 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import com.yoho.search.common.cache.impls.SearchRedis;
import com.yoho.search.common.filter.YohoHttpServletRequestWrapper;
@Component
@Aspect
public class AutoDownGradePersionalAspect {
private static final Logger logger = LoggerFactory.getLogger(AutoDownGradePersionalAspect.class);
private static final Logger logger = LoggerFactory.getLogger("DOWNGRADE");
@Autowired
private SearchRedis searchRedis;
private AutoDownGradePersionalRateLimitService autoDownGradePersionalRateLimitService;
@Around("@annotation(com.yoho.search.common.downgrade.persional.AutoDownGradePersional)")
public Object downGrade(ProceedingJoinPoint pjp) throws Throwable {
String autoDownGradeKey = this.getAutoDownGradeKey(pjp);
boolean isPersional = false;
try {
String autoDownGradeKey = this.getAutoDownGradeKey(pjp);
MethodSignature signature = (MethodSignature) pjp.getSignature();
AutoDownGradePersional autoDownGrade = signature.getMethod().getAnnotation(AutoDownGradePersional.class);
Object[] arges = pjp.getArgs();
for (Object object : arges) {
if (this.dealPersional(object, autoDownGrade, autoDownGradeKey)) {
isPersional = true;
break;
}
}
... ... @@ -44,10 +40,6 @@ public class AutoDownGradePersionalAspect {
} catch (Exception e) {
logger.error(e.getMessage());
throw e;
} finally {
if (isPersional) {
this.decrease(autoDownGradeKey);
}
}
}
... ... @@ -63,33 +55,36 @@ public class AutoDownGradePersionalAspect {
if (StringUtils.isNotBlank(yohoHttpServletRequestWrapper.getParameter("order"))) {
return false;
}
if (autoDownGrade == null) {
return false;
}
int count = this.increase(autoDownGradeKey, autoDownGrade.timeInSecond());
if (count >= autoDownGrade.maxCount()) {
logger.error("AutoDownGradePersionalAspect,autoDownGradeKey is [{}]", autoDownGradeKey);
int rateLimitInSecond = autoDownGrade.rateLimitInSecond();
int rateLimit = autoDownGrade.rateLimit();
if (autoDownGradePersionalRateLimitService.isRateLimit(autoDownGradeKey, rateLimitInSecond, rateLimit)) {
logger.error("AutoDownGradePersionalAspect,autoDownGradeKey is [{}],rateLimitInSecond is [{}],rateLimit is [{}]", autoDownGradeKey, rateLimitInSecond, rateLimit);
yohoHttpServletRequestWrapper.addParams("uid", new String[] { "0" });
return true;
}
return true;
return false;
}
private String getAutoDownGradeKey(ProceedingJoinPoint pjp) {
// 1、获取method和class
Method targetMethod = ((MethodSignature) (pjp.getSignature())).getMethod();
Class<?> clazz = targetMethod.getDeclaringClass();
// 2、获取class上的requestMapping
String classRequestMappingValue = "";
RequestMapping classRequestMapping = clazz.getDeclaredAnnotation(RequestMapping.class);
if (classRequestMapping != null && classRequestMapping.value() != null && classRequestMapping.value().length > 0) {
classRequestMappingValue = classRequestMapping.value()[0];
}
// 3、获取method上的requestMapping
String methodRequestMappingValue = "";
RequestMapping methodRequestMapping = targetMethod.getDeclaredAnnotation(RequestMapping.class);
if (methodRequestMapping != null && methodRequestMapping.value() != null && methodRequestMapping.value().length > 0) {
methodRequestMappingValue = methodRequestMapping.value()[0];
}
// 4、获取key
if (StringUtils.isNotBlank(classRequestMappingValue) || StringUtils.isNotBlank(methodRequestMappingValue)) {
return classRequestMappingValue + methodRequestMappingValue;
} else {
... ... @@ -97,21 +92,4 @@ public class AutoDownGradePersionalAspect {
}
}
private int increase(String autoDownGradeKey, long expireInSeconds) {
if (!searchRedis.searchRedisTemplate.hasKey(autoDownGradeKey)) {
// 回调 计数器使用者, 初始化计数器
String initialValue = String.valueOf(0);
// 如果已经被初始化过, 则不用再初始化, 因为其他线程可能已经进行了 increase, 所以必须使用 setIfAbsent
searchRedis.searchValueOperations.setIfAbsent(autoDownGradeKey, initialValue);
// 设置有效期, redis所有的key, 必须设置有效期
searchRedis.searchRedisTemplate.longExpire(autoDownGradeKey, expireInSeconds, TimeUnit.SECONDS);
}
// 原子性对值修改delta数值
return searchRedis.searchValueOperations.increment(autoDownGradeKey, 1).intValue();
}
private int decrease(String autoDownGradeKey) {
return searchRedis.searchValueOperations.increment(autoDownGradeKey, -1).intValue();
}
}
... ...
package com.yoho.search.common.downgrade.persional;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yoho.search.common.cache.impls.SearchRedis;
@Service
public class AutoDownGradePersionalRateLimitService {
@Autowired
private SearchRedis searchRedis;
public boolean isRateLimit(String key, int rateLimitInSecond, int rateLimit) {
if (!searchRedis.searchRedisTemplate.hasKey(key)) {
// 如果已经被初始化过, 则不用再初始化, 因为其他线程可能已经进行了 increase, 所以必须使用 setIfAbsent
searchRedis.searchValueOperations.setIfAbsent(key, "0");
// 设置有效期, redis所有的key, 必须设置有效期
searchRedis.searchRedisTemplate.longExpire(key, rateLimitInSecond, TimeUnit.SECONDS);
}
// 原子性对值修改delta数值
return searchRedis.searchValueOperations.increment(key, 1).intValue() > rateLimit;
}
}
... ...
... ... @@ -26,7 +26,6 @@ public class YohoHttpServletRequestWrapper extends HttpServletRequestWrapper {
@Override
public String getParameter(String name) {
String result = "";
Object v = params.get(name);
if (v == null) {
result = null;
... ... @@ -42,7 +41,6 @@ public class YohoHttpServletRequestWrapper extends HttpServletRequestWrapper {
} else {
result = v.toString();
}
return result;
}
... ... @@ -59,7 +57,6 @@ public class YohoHttpServletRequestWrapper extends HttpServletRequestWrapper {
@Override
public String[] getParameterValues(String name) {
String[] result = null;
Object v = params.get(name);
if (v == null) {
result = null;
... ... @@ -70,7 +67,6 @@ public class YohoHttpServletRequestWrapper extends HttpServletRequestWrapper {
} else {
result = new String[] { v.toString() };
}
return result;
}
... ...
... ... @@ -29,14 +29,14 @@ public class ProductListController {
*
* @return
*/
@AutoDownGradePersional(timeInSecond = 10, maxCount = 100)
@AutoDownGradePersional(rateLimitInSecond = 10, rateLimit = 100)
@RequestMapping(method = RequestMethod.GET, value = "/productindex/productList")
@ResponseBody
public SearchApiResult productList(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return productListService.productList(paramMap);
}
/**
* 获取商品列表,返回product_skn
*
... ...