Lors de la conception du système, nous aurons une capacité estimée du système. Si elle dépasse le seuil TPS/QPS que le système peut supporter pendant une longue période, le système peut être submergé. ce qui finit par rendre l'ensemble du service non disponible. Afin d'éviter cette situation, nous devons limiter le flux de demandes d'interface.
Ainsi, nous pouvons protéger le système ou éviter un gaspillage inutile de ressources en limitant le taux de demandes d'accès simultanées ou le nombre de demandes dans une fenêtre de temps. Une fois la limite de débit atteinte, nous pouvons refuser le service, faire la queue ou attendre.
Le système dispose d'une interface pour obtenir les codes de vérification SMS des téléphones portables, car il s'agit d'une interface ouverte, afin d'éviter que les utilisateurs n'envoient constamment des demandes pour obtenir des codes de vérification et empêcher les tentatives malveillantes de balayage. l'interface, nous utilisons la dernière méthode de compteur simple pour limiter le flux actuel, limitant chaque IP à une seule requête par minute, puis la limite de fenêtre de temps de chaque autre numéro de téléphone mobile est jugée par la logique métier. Généralement, certaines interfaces ont un nombre de visites relativement important et peuvent saturer le système, il faut donc ajouter des restrictions de circulation ! Tels que : vente flash, etc...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimiter {
/**
* 限流key
*/
String key() default Constants.RATE_LIMIT_KEY;
/**
* 限流时间,单位秒
*/
int time() default 60;
/**
* 限流次数
*/
int count() default 100;
/**
* 限流类型
*/
LimitType limitType() default LimitType.DEFAULT;
/**
* 限流后返回的文字
*/
String limitMsg() default "访问过于频繁,请稍候再试";
}@Aspect
@Component
public class RateLimiterAspect {
private final static Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);
@Autowired
private RedisUtils redisUtils;
@Before("@annotation(rateLimiter)")
public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable {
int time = rateLimiter.time();
int count = rateLimiter.count();
long total = 1L;
String combineKey = getCombineKey(rateLimiter, point);
try
{
if(redisUtils.hasKey(combineKey)){
total = redisUtils.incr(combineKey,1); //请求进来,对应的key加1
if(total > count)
throw new ServiceRuntimeException(rateLimiter.limitMsg());
}else{
redisUtils.set(combineKey,1,time); //初始化key
}
}
catch (ServiceRuntimeException e)
{
throw e;
}
catch (Exception e)
{
throw new ServiceRuntimeException("网络繁忙,请稍候再试");
}
}
/**
* 获取限流key
* @param rateLimiter
* @param point
* @return
*/
public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) {
StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
if (rateLimiter.limitType() == LimitType.IP)
{
stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())).append("-");
}
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
Class<?> targetClass = method.getDeclaringClass();
stringBuffer.append(targetClass.getName()).append("-").append(method.getName());
return stringBuffer.toString();
}
}@RestController
public class TestController {
@RateLimiter(time = 60, count = 1, limitType = LimitType.IP, limitMsg = "一分钟内只能请求一次,请稍后重试")
@GetMapping("/hello")
public ResultMsg hello() {
return ResultMsg.success("Hello World!");
}
}1) La première fois que vous l'enverrez, le résultat sera renvoyé normalement

2) La deuxième fois que vous l'enverrez dans la minute, vous obtiendrez une erreur et une invite de limite actuelle

Le ci-dessus est la AOP + Redis solution pour mettre en œuvre la limite de courant de l'interface, vous avez perdu vos études ?
Il existe d'autres méthodes de limitation de courant, telles que la méthode de limitation de courant par fenêtre coulissante (plus rigoureuse que le compteur), le seau à jetons, etc... Les amis intéressés peuvent en apprendre davantage.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!
Introduction aux types d'interfaces de disque dur
Comment exécuter le projet phpstudy
Comment revenir à la page d'accueil en HTML
Comment ouvrir des fichiers php sur un téléphone mobile
modifier l'adresse IP
Que faire si le système d'installation ne trouve pas le disque dur
Comment ouvrir un fichier zip
écran de téléphone portable tft