Authored by hugufei

自定降级代码提交

  1 +package com.yoho.search.common.downgrade.persional;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +@Target({ ElementType.METHOD })
  9 +@Retention(RetentionPolicy.RUNTIME)
  10 +public @interface AutoDownGradePersional {
  11 +
  12 + public int timeInSecond();
  13 +
  14 + public int maxCount();
  15 +
  16 +}
  1 +package com.yoho.search.common.downgrade.persional;
  2 +
  3 +import java.lang.reflect.Method;
  4 +import java.util.concurrent.TimeUnit;
  5 +
  6 +import org.apache.commons.lang.StringUtils;
  7 +import org.aspectj.lang.ProceedingJoinPoint;
  8 +import org.aspectj.lang.annotation.Around;
  9 +import org.aspectj.lang.annotation.Aspect;
  10 +import org.aspectj.lang.reflect.MethodSignature;
  11 +import org.slf4j.Logger;
  12 +import org.slf4j.LoggerFactory;
  13 +import org.springframework.beans.factory.annotation.Autowired;
  14 +import org.springframework.stereotype.Component;
  15 +import org.springframework.web.bind.annotation.RequestMapping;
  16 +
  17 +import com.yoho.search.common.cache.impls.SearchRedis;
  18 +import com.yoho.search.common.filter.YohoHttpServletRequestWrapper;
  19 +
  20 +@Component
  21 +@Aspect
  22 +public class AutoDownGradePersionalAspect {
  23 +
  24 + private static final Logger logger = LoggerFactory.getLogger(AutoDownGradePersionalAspect.class);
  25 +
  26 + @Autowired
  27 + private SearchRedis searchRedis;
  28 +
  29 + @Around("@annotation(com.yoho.search.common.downgrade.persional.AutoDownGradePersional)")
  30 + public Object downGrade(ProceedingJoinPoint pjp) throws Throwable {
  31 + String autoDownGradeKey = this.getAutoDownGradeKey(pjp);
  32 + boolean isPersional = false;
  33 + try {
  34 + MethodSignature signature = (MethodSignature) pjp.getSignature();
  35 + AutoDownGradePersional autoDownGrade = signature.getMethod().getAnnotation(AutoDownGradePersional.class);
  36 + Object[] arges = pjp.getArgs();
  37 + for (Object object : arges) {
  38 + if (this.dealPersional(object, autoDownGrade, autoDownGradeKey)) {
  39 + isPersional = true;
  40 + break;
  41 + }
  42 + }
  43 + return pjp.proceed();
  44 + } catch (Exception e) {
  45 + logger.error(e.getMessage());
  46 + throw e;
  47 + } finally {
  48 + if (isPersional) {
  49 + this.decrease(autoDownGradeKey);
  50 + }
  51 + }
  52 + }
  53 +
  54 + private boolean dealPersional(Object object, AutoDownGradePersional autoDownGrade, String autoDownGradeKey) {
  55 + if (!(object instanceof YohoHttpServletRequestWrapper)) {
  56 + return false;
  57 + }
  58 + YohoHttpServletRequestWrapper yohoHttpServletRequestWrapper = (YohoHttpServletRequestWrapper) object;
  59 + String uid = yohoHttpServletRequestWrapper.getParameter("uid");
  60 + if (StringUtils.isBlank(uid) || "0".equalsIgnoreCase(uid)) {
  61 + return false;
  62 + }
  63 + if (StringUtils.isNotBlank(yohoHttpServletRequestWrapper.getParameter("order"))) {
  64 + return false;
  65 + }
  66 + if (autoDownGrade == null) {
  67 + return false;
  68 + }
  69 + int count = this.increase(autoDownGradeKey, autoDownGrade.timeInSecond());
  70 + if (count >= autoDownGrade.maxCount()) {
  71 + logger.error("AutoDownGradePersionalAspect,autoDownGradeKey is [{}]", autoDownGradeKey);
  72 + yohoHttpServletRequestWrapper.addParams("uid", new String[] { "0" });
  73 + }
  74 + return true;
  75 + }
  76 +
  77 + private String getAutoDownGradeKey(ProceedingJoinPoint pjp) {
  78 + Method targetMethod = ((MethodSignature) (pjp.getSignature())).getMethod();
  79 + Class<?> clazz = targetMethod.getDeclaringClass();
  80 +
  81 + String classRequestMappingValue = "";
  82 + RequestMapping classRequestMapping = clazz.getDeclaredAnnotation(RequestMapping.class);
  83 + if (classRequestMapping != null && classRequestMapping.value() != null && classRequestMapping.value().length > 0) {
  84 + classRequestMappingValue = classRequestMapping.value()[0];
  85 + }
  86 +
  87 + String methodRequestMappingValue = "";
  88 + RequestMapping methodRequestMapping = targetMethod.getDeclaredAnnotation(RequestMapping.class);
  89 + if (methodRequestMapping != null && methodRequestMapping.value() != null && methodRequestMapping.value().length > 0) {
  90 + methodRequestMappingValue = methodRequestMapping.value()[0];
  91 + }
  92 +
  93 + if (StringUtils.isNotBlank(classRequestMappingValue) || StringUtils.isNotBlank(methodRequestMappingValue)) {
  94 + return classRequestMappingValue + methodRequestMappingValue;
  95 + } else {
  96 + return clazz.getName() + '_' + targetMethod.getName();
  97 + }
  98 + }
  99 +
  100 + private int increase(String autoDownGradeKey, long expireInSeconds) {
  101 + if (!searchRedis.searchRedisTemplate.hasKey(autoDownGradeKey)) {
  102 + // 回调 计数器使用者, 初始化计数器
  103 + String initialValue = String.valueOf(0);
  104 + // 如果已经被初始化过, 则不用再初始化, 因为其他线程可能已经进行了 increase, 所以必须使用 setIfAbsent
  105 + searchRedis.searchValueOperations.setIfAbsent(autoDownGradeKey, initialValue);
  106 + // 设置有效期, redis所有的key, 必须设置有效期
  107 + searchRedis.searchRedisTemplate.longExpire(autoDownGradeKey, expireInSeconds, TimeUnit.SECONDS);
  108 + }
  109 + // 原子性对值修改delta数值
  110 + return searchRedis.searchValueOperations.increment(autoDownGradeKey, 1).intValue();
  111 + }
  112 +
  113 + private int decrease(String autoDownGradeKey) {
  114 + return searchRedis.searchValueOperations.increment(autoDownGradeKey, -1).intValue();
  115 + }
  116 +
  117 +}
  1 +package com.yoho.search.common.filter;
  2 +
  3 +import java.io.IOException;
  4 +
  5 +import javax.servlet.Filter;
  6 +import javax.servlet.FilterChain;
  7 +import javax.servlet.FilterConfig;
  8 +import javax.servlet.ServletException;
  9 +import javax.servlet.ServletRequest;
  10 +import javax.servlet.ServletResponse;
  11 +import javax.servlet.http.HttpServletRequest;
  12 +
  13 +public class YohoHttpServletRequestFilter implements Filter {
  14 +
  15 + @Override
  16 + public void init(FilterConfig filterConfig) throws ServletException {
  17 + // TODO Auto-generated method stub
  18 + }
  19 +
  20 + @Override
  21 + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  22 + HttpServletRequest httpServletRequest = (HttpServletRequest) request;
  23 + YohoHttpServletRequestWrapper yohoHttpServletRequestWrapper = new YohoHttpServletRequestWrapper(httpServletRequest);
  24 + chain.doFilter(yohoHttpServletRequestWrapper, response);
  25 + }
  26 +
  27 + @Override
  28 + public void destroy() {
  29 + // TODO Auto-generated method stub
  30 + }
  31 +
  32 +}
  1 +package com.yoho.search.common.filter;
  2 +
  3 +import java.util.Enumeration;
  4 +import java.util.HashMap;
  5 +import java.util.Map;
  6 +import java.util.Vector;
  7 +
  8 +import javax.servlet.http.HttpServletRequest;
  9 +import javax.servlet.http.HttpServletRequestWrapper;
  10 +
  11 +public class YohoHttpServletRequestWrapper extends HttpServletRequestWrapper {
  12 +
  13 + private Map<String, String[]> params;
  14 +
  15 + public YohoHttpServletRequestWrapper(HttpServletRequest request) {
  16 + super(request);
  17 + this.params = new HashMap<String, String[]>();
  18 + this.params.putAll(request.getParameterMap());
  19 + }
  20 +
  21 + public YohoHttpServletRequestWrapper addParams(String key, String[] values) {
  22 + this.params.put(key, values);
  23 + return this;
  24 + }
  25 +
  26 + @Override
  27 + public String getParameter(String name) {
  28 + String result = "";
  29 +
  30 + Object v = params.get(name);
  31 + if (v == null) {
  32 + result = null;
  33 + } else if (v instanceof String[]) {
  34 + String[] strArr = (String[]) v;
  35 + if (strArr.length > 0) {
  36 + result = strArr[0];
  37 + } else {
  38 + result = null;
  39 + }
  40 + } else if (v instanceof String) {
  41 + result = (String) v;
  42 + } else {
  43 + result = v.toString();
  44 + }
  45 +
  46 + return result;
  47 + }
  48 +
  49 + @Override
  50 + public Map<String, String[]> getParameterMap() {
  51 + return params;
  52 + }
  53 +
  54 + @Override
  55 + public Enumeration<String> getParameterNames() {
  56 + return new Vector<String>(params.keySet()).elements();
  57 + }
  58 +
  59 + @Override
  60 + public String[] getParameterValues(String name) {
  61 + String[] result = null;
  62 +
  63 + Object v = params.get(name);
  64 + if (v == null) {
  65 + result = null;
  66 + } else if (v instanceof String[]) {
  67 + result = (String[]) v;
  68 + } else if (v instanceof String) {
  69 + result = new String[] { (String) v };
  70 + } else {
  71 + result = new String[] { v.toString() };
  72 + }
  73 +
  74 + return result;
  75 + }
  76 +
  77 +}
@@ -19,27 +19,28 @@ import com.yoho.search.common.utils.HttpServletRequestUtils; @@ -19,27 +19,28 @@ import com.yoho.search.common.utils.HttpServletRequestUtils;
19 19
20 /** 20 /**
21 * 耗时拦截器 21 * 耗时拦截器
  22 + *
22 * @author gufei.hu 23 * @author gufei.hu
23 * 24 *
24 */ 25 */
25 public class ControllerCostInterceptor implements HandlerInterceptor { 26 public class ControllerCostInterceptor implements HandlerInterceptor {
26 27
27 private static final Logger CONTROLLER_COST = LoggerFactory.getLogger("CONTROLLER_COST"); 28 private static final Logger CONTROLLER_COST = LoggerFactory.getLogger("CONTROLLER_COST");
28 - 29 +
29 private static final Logger CONTROLLER_PERFORMANCE = LoggerFactory.getLogger("CONTROLLER_PERFORMANCE"); 30 private static final Logger CONTROLLER_PERFORMANCE = LoggerFactory.getLogger("CONTROLLER_PERFORMANCE");
30 31
31 private static final ThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("ThreadLocal StartTime"); 32 private static final ThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("ThreadLocal StartTime");
32 - 33 +
33 @Autowired 34 @Autowired
34 private DownGradeService downGradeService; 35 private DownGradeService downGradeService;
35 - 36 +
36 private PerformanceMonitor monitor; 37 private PerformanceMonitor monitor;
37 38
38 @PostConstruct 39 @PostConstruct
39 - void init(){  
40 - monitor = new PerformanceMonitor("CONTROLLER_PERFORMANCE",CONTROLLER_PERFORMANCE, 10); 40 + void init() {
  41 + monitor = new PerformanceMonitor("CONTROLLER_PERFORMANCE", CONTROLLER_PERFORMANCE, 10);
41 } 42 }
42 - 43 +
43 @Override 44 @Override
44 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handle) throws Exception { 45 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handle) throws Exception {
45 long beginTime = System.currentTimeMillis();// 1、开始时间 46 long beginTime = System.currentTimeMillis();// 1、开始时间
@@ -51,7 +52,7 @@ public class ControllerCostInterceptor implements HandlerInterceptor { @@ -51,7 +52,7 @@ public class ControllerCostInterceptor implements HandlerInterceptor {
51 52
52 @Override 53 @Override
53 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) throws Exception { 54 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) throws Exception {
54 - 55 +
55 } 56 }
56 57
57 @Override 58 @Override
1 package com.yoho.search.restapi; 1 package com.yoho.search.restapi;
2 2
3 -import com.alibaba.fastjson.JSONObject;  
4 -import com.yoho.search.common.utils.HttpServletRequestUtils;  
5 -import com.yoho.search.models.SearchApiResult;  
6 -import com.yoho.search.service.service.IProductListService; 3 +import java.util.HashMap;
  4 +import java.util.Map;
  5 +
  6 +import javax.servlet.http.HttpServletRequest;
7 7
8 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.beans.factory.annotation.Autowired;
9 import org.springframework.stereotype.Controller; 9 import org.springframework.stereotype.Controller;
@@ -12,10 +12,11 @@ import org.springframework.web.bind.annotation.RequestMapping; @@ -12,10 +12,11 @@ import org.springframework.web.bind.annotation.RequestMapping;
12 import org.springframework.web.bind.annotation.RequestMethod; 12 import org.springframework.web.bind.annotation.RequestMethod;
13 import org.springframework.web.bind.annotation.ResponseBody; 13 import org.springframework.web.bind.annotation.ResponseBody;
14 14
15 -import javax.servlet.http.HttpServletRequest;  
16 -  
17 -import java.util.HashMap;  
18 -import java.util.Map; 15 +import com.alibaba.fastjson.JSONObject;
  16 +import com.yoho.search.common.downgrade.persional.AutoDownGradePersional;
  17 +import com.yoho.search.common.utils.HttpServletRequestUtils;
  18 +import com.yoho.search.models.SearchApiResult;
  19 +import com.yoho.search.service.service.IProductListService;
19 20
20 @Controller 21 @Controller
21 public class ProductListController { 22 public class ProductListController {
@@ -28,6 +29,7 @@ public class ProductListController { @@ -28,6 +29,7 @@ public class ProductListController {
28 * 29 *
29 * @return 30 * @return
30 */ 31 */
  32 + @AutoDownGradePersional(timeInSecond = 10, maxCount = 0)
31 @RequestMapping(method = RequestMethod.GET, value = "/productindex/productList") 33 @RequestMapping(method = RequestMethod.GET, value = "/productindex/productList")
32 @ResponseBody 34 @ResponseBody
33 public SearchApiResult productList(HttpServletRequest request) { 35 public SearchApiResult productList(HttpServletRequest request) {
@@ -46,7 +48,7 @@ public class ProductListController { @@ -46,7 +48,7 @@ public class ProductListController {
46 Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request); 48 Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
47 return productListService.productListWithPhrase(paramMap); 49 return productListService.productListWithPhrase(paramMap);
48 } 50 }
49 - 51 +
50 /** 52 /**
51 * 获取商品列表 53 * 获取商品列表
52 * 54 *
1 package com.yoho.search.service.service; 1 package com.yoho.search.service.service;
2 2
3 -import com.yoho.search.models.SearchApiResult;  
4 -  
5 import java.util.Map; 3 import java.util.Map;
6 4
  5 +import com.yoho.search.models.SearchApiResult;
  6 +
7 public interface IProductListService { 7 public interface IProductListService {
8 8
9 /** 9 /**
@@ -80,7 +80,7 @@ public class ProductListServiceImpl implements IProductListService { @@ -80,7 +80,7 @@ public class ProductListServiceImpl implements IProductListService {
80 void init() { 80 void init() {
81 productListSearchCache = searchCacheFactory.getProductListSearchCache(); 81 productListSearchCache = searchCacheFactory.getProductListSearchCache();
82 } 82 }
83 - 83 +
84 @Override 84 @Override
85 public SearchApiResult productList(Map<String, String> paramMap) { 85 public SearchApiResult productList(Map<String, String> paramMap) {
86 try { 86 try {
@@ -52,6 +52,21 @@ @@ -52,6 +52,21 @@
52 <filter-name>encodingFilter</filter-name> 52 <filter-name>encodingFilter</filter-name>
53 <url-pattern>/*</url-pattern> 53 <url-pattern>/*</url-pattern>
54 </filter-mapping> 54 </filter-mapping>
  55 +
  56 + <!-- yohoHttpRequest过滤器 -->
  57 + <filter>
  58 + <filter-name>yohoHttpRequestFilter</filter-name>
  59 + <filter-class>com.yoho.search.common.filter.YohoHttpServletRequestFilter</filter-class>
  60 + <async-supported>true</async-supported>
  61 + <init-param>
  62 + <param-name>encoding</param-name>
  63 + <param-value>UTF-8</param-value>
  64 + </init-param>
  65 + </filter>
  66 + <filter-mapping>
  67 + <filter-name>yohoHttpRequestFilter</filter-name>
  68 + <url-pattern>/*</url-pattern>
  69 + </filter-mapping>
55 70
56 <!-- 防止Spring内存溢出监听器 --> 71 <!-- 防止Spring内存溢出监听器 -->
57 <listener> 72 <listener>