Showing
9 changed files
with
279 additions
and
19 deletions
service/src/main/java/com/yoho/search/common/downgrade/persional/AutoDownGradePersional.java
0 → 100644
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 | +} |
service/src/main/java/com/yoho/search/common/downgrade/persional/AutoDownGradePersionalAspect.java
0 → 100644
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> |
-
Please register or login to post a comment