In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)05/31 Report--
Most people do not understand the knowledge of this article "how to use AOP+redis+lua to limit current", so the editor summarizes the following content, detailed content, clear steps, and has a certain reference value. I hope you can get something after reading this article. Let's take a look at this "how to use AOP+redis+lua to do current limit" article.
Demand
The company uses OneByOne to delete data. In order to prevent too much data from being deleted within a period of time, let me limit the flow of an API. If an exception is reported when a certain threshold is exceeded, the deletion operation will be terminated.
Mode of realization
Create a custom annotation @ limit that allows users to configure count (maximum number of visits in a certain period of time) and period (given time range), that is, access frequency, where they need it. Then the request of the method is intercepted by LimitInterceptor and the access frequency is controlled by redis+lua script.
Source code Limit comments
Access frequency count, period used to configure the method
Import javax.validation.constraints.Min;import java.lang.annotation.*;@Target ({ElementType.METHOD, ElementType.TYPE}) @ Retention (RetentionPolicy.RUNTIME) @ Inherited@Documentedpublic @ interface Limit {/ * key * / String key () default ""; / * * Key prefix * / String prefix () default "" / * maximum number of visits within a certain period of time * / @ Min (1) int count (); / * given time range unit (seconds) * / @ Min (1) int period (); / * types of current restrictions (user-defined key or request ip) * / LimitType limitType () default LimitType.CUSTOMER;} LimitKey
Used to mark parameters as part of the redis key value
Import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target (ElementType.PARAMETER) @ Retention (RetentionPolicy.RUNTIME) public @ interface LimitKey {} LimitType
Enumeration, the type of redis key value, supports custom key and obtaining key from ip and methodName
Public enum LimitType {/ * Custom key * / CUSTOMER, / * requester IP * / IP, / * method name * / METHOD_NAME;} RedisLimiterHelper
Initialize a redisTemplate Bean used for current restriction
Import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;import java.io.Serializable;@Configurationpublic class RedisLimiterHelper {@ Bean public RedisTemplate limitRedisTemplate (@ Qualifier ("defaultStringRedisTemplate") StringRedisTemplate redisTemplate) {RedisTemplate template = new RedisTemplate () Template.setKeySerializer (new StringRedisSerializer ()); template.setValueSerializer (new GenericJackson2JsonRedisSerializer ()); template.setConnectionFactory (redisTemplate.getConnectionFactory ()); return template;}} LimitInterceptor
Use aop to intercept requests and control access frequency
Import com.google.common.collect.ImmutableList;import com.yxt.qida.api.bean.service.xxv2.openapi.anno.Limit;import com.yxt.qida.api.bean.service.xxv2.openapi.anno.LimitKey;import com.yxt.qida.api.bean.service.xxv2.openapi.anno.LimitType;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang3.ArrayUtils;import org.apache.commons.lang3.StringUtils;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around Import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.script.DefaultRedisScript;import org.springframework.data.redis.core.script.RedisScript;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;import java.io.Serializable Import java.lang.annotation.Annotation;import java.lang.reflect.Method;@Slf4j@Aspect@Configurationpublic class LimitInterceptor {private static final String UNKNOWN = "unknown"; private final RedisTemplate limitRedisTemplate; @ Autowired public LimitInterceptor (RedisTemplate limitRedisTemplate) {this.limitRedisTemplate = limitRedisTemplate } @ Around ("execution (public * * (..)) & & @ annotation (com.yxt.qida.api.bean.service.xxv2.openapi.anno.Limit)") public Object interceptor (ProceedingJoinPoint pjp) {MethodSignature signature = (MethodSignature) pjp.getSignature (); Method method = signature.getMethod (); Limit limitAnnotation = method.getAnnotation (Limit.class); LimitType limitType = limitAnnotation.limitType (); int limitPeriod = limitAnnotation.period () Int limitCount = limitAnnotation.count (); / * get different key according to the current limit type. If you don't pass it, we will use the method name as key * / String key; switch (limitType) {case IP: key = getIpAddress (); break Case CUSTOMER: key = limitAnnotation.key (); break; case METHOD_NAME: String methodName = method.getName (); key = StringUtils.upperCase (methodName); break; default: throw new RuntimeException ("limitInterceptor-invalid enumeration value") } / * get the annotated key, which is the highest priority and overrides the previous key value * / Object [] args = pjp.getArgs (); Annotation [] [] paramAnnoAry = method.getParameterAnnotations (); for (Annotation [] item: paramAnnoAry) {int paramIndex = ArrayUtils.indexOf (paramAnnoAry, item) For (Annotation anno: item) {if (anno instanceof LimitKey) {Object arg = args [paramIndex]; if (arg instanceof String & & StringUtils.isNotBlank ((String) arg)) {key = (String) arg; break } if (StringUtils.isBlank (key)) {throw new RuntimeException ("limitInterceptor-key value cannot be empty");} String prefix = limitAnnotation.prefix (); String [] keyAry = StringUtils.isBlank (prefix)? New String [] {"limit", key}: new String [] {"limit", prefix, key}; ImmutableList keys = ImmutableList.of (StringUtils.join (keyAry, "-")); try {String luaScript = buildLuaScript (); RedisScript redisScript = new DefaultRedisScript (luaScript, Number.class); Number count = limitRedisTemplate.execute (redisScript, keys, limitCount, limitPeriod); if (count! = null & count.intValue ()
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.