ホームページ  >  記事  >  Java  >  Springboot を使用して RateLimiter 電流制限を統合する方法

Springboot を使用して RateLimiter 電流制限を統合する方法

WBOY
WBOY転載
2023-05-12 10:40:061605ブラウズ

RateLimiter トークン バケットの図式

Springboot を使用して RateLimiter 電流制限を統合する方法

  • 時間が経過すると、システムは一定の 1/QPS 時間間隔に従います (QPS=100 の場合、間隔は 10 ミリ秒です) バケツにトークンを追加します (漏れの逆を想像してください。常に水を追加する蛇口があります)、バケツがいっぱいの場合、それ以上追加されません。新しいリクエストが来ると、それぞれがトークンを奪います。利用可能なトークンがない場合は、サービスがブロックまたは拒否されます。

  • トークン バケットのもう 1 つの利点は、速度を簡単に変更できることです。速度を上げる必要がある場合は、必要に応じて増やしてバケットに入れます。トークンのレート。一般に、特定の数のトークンが定期的にバケットに追加されます (100 ミリ秒など)。一部のバリアント アルゴリズムは、追加する必要があるトークンの数を計算します。

トークン バケットは、一般的に使用されるトラフィック制御テクノロジです。トークン バケット自体には、破棄ポリシーや優先ポリシーはありません。

原則

1.トークンは一定の割合でバケットに入れられます。

2.各トークンにより、ソースは特定のビット数を送信できます。

3.パケットを送信するために、トラフィック コンディショナーはパケット サイズと同じ数のトークンをバケットから削除します。

4.パケットを送信するのに十分なトークンがない場合、パケットは十分なトークンが揃うまで待機するか (シェーパーの場合)、パケットはドロップされ、場合によってはより低い DSCP でマークされます (ポリシーラーの場合)。 ####5.バケットには特定の容量があり、バケットがいっぱいになると、新しく追加されたトークンは破棄されます。したがって、ソースがいつでもネットワーク上に送信できるバースト データの最大量はバケット サイズに比例します。トークン バケットではバーストが許可されますが、制限を超えることはできません。

#メソッドの概要

修飾子と型メソッドと説明acquire() RateLimiter から権限を取得します。このメソッドはリクエストが取得されるまでブロックされます. acquire(int alloweds) RateLimiter から指定された数の許可を取得します。このメソッドはリクエストが取得されるまでブロックされます create(double allowedsPerSecond) 指定された安定したスループット レートに基づいて RateLimiter を作成します。スループット レートは 1 秒あたりの許可数 (通常は QPS、1 あたりのクエリ数) を指します。 Second)create(doublemitsPerSecond,longwarmupPeriod,TimeUnitunit) 指定された安定したスループットレートとウォームアップ期間に基づいて RateLimiter を作成します。ここでのスループット レートは 1 秒あたりの量を指します ライセンスの数 (通常は QPS、1 秒あたりのリクエスト数を指します) このウォームアップ期間中、RateLimiter によって割り当てられる 1 秒あたりのライセンスの数は、最大値に達するまで着実に増加します。ウォームアップ期間の終了時のレート。 (飽和するのに十分なリクエストがある限り) getRate() RateLimiter 設定の安定したレートを 1 秒あたりのライセンス単位で返します setRate(double allowedsPerSecond) は、RateLimite の安定したレートを更新します。パラメータpermitsPerSecond は、RateLimiter を構築するファクトリ メソッドによって提供されます。 toString() オブジェクトの文字表現を返します。tryAcquire( ) 遅延なく即座に権限を取得できる場合は、RateLimiter から権限を取得します。tryAcquire(int alloweds) RateLimiter から権限の数を取得します。許可の数を遅滞なく即座に取得できる tryAcquire(int Permits, Long timeout, TimeUnit Unit) RateLimiter から指定された数を取得します。タイムアウトを超えない期間内にライセンスの数を取得できる場合、またはタイムアウトが経過するまでにライセンスの数を取得できない場合は、すぐに false が返されます (待つ必要はありません) tryAcquire(long timeout, TimeUnit単位) RateLimiterから許可を取得 タイムアウトを超えない時間内に許可を取得できた場合、またはタイムアウトまでに許可を取得できなかった場合はリターンすぐに false (待つ必要はありません)コードの投稿を開始pom.xml
double
double
static RateLimiter
static RateLimiter
double
void
String
boolean
boolean
#boolean
boolean
<!--guava RateLimiter限流-->
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>28.2-jre</version>
</dependency>

カスタム インターフェイス制限

package com.zjy.knife4j.inte;
import java.lang.annotation.*;
/**
 * 限流注解
 */
@Inherited
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Limit {
    // 默认每秒放入桶中的token
    double limitNum() default 20;
    String name() default "";
}

aop アスペクト

package com.zjy.knife4j.aspect;
import com.google.common.util.concurrent.RateLimiter;
import com.zjy.knife4j.inte.Limit;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
@Aspect
@Component
public class RateLimitAspect {
    /**日志对象*/
    private static final Logger logger = LoggerFactory.getLogger(RateLimitAspect.class);
    private ConcurrentHashMap<String, RateLimiter> RATE_LIMITER  = new ConcurrentHashMap<>();
    private RateLimiter rateLimiter;
    @Pointcut("@annotation(com.zjy.knife4j.inte.Limit)")
    public void serviceLimit() {
    }
    @Around("serviceLimit()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Object obj = null;
        //获取拦截的方法名
        Signature sig = point.getSignature();
        //获取拦截的方法名
        MethodSignature msig = (MethodSignature) sig;
        //返回被织入增加处理目标对象
        Object target = point.getTarget();
        //为了获取注解信息
        Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
        //获取注解信息
        Limit annotation = currentMethod.getAnnotation(Limit.class);
        double limitNum = annotation.limitNum(); //获取注解每秒加入桶中的token
        String functionName = msig.getName(); // 注解所在方法名区分不同的限流策略
        if(RATE_LIMITER.containsKey(functionName)){
            rateLimiter=RATE_LIMITER.get(functionName);
        }else {
            RATE_LIMITER.put(functionName, RateLimiter.create(limitNum));
            rateLimiter=RATE_LIMITER.get(functionName);
        }
        if(rateLimiter.tryAcquire()) {
            logger.info("执行成功!!!...做一些业务处理");
            return point.proceed();
        } else {
            logger.info("请求繁忙...做一些业务处理");
            return null;
        }
    }
}

RateLimiterController

package com.zjy.knife4j.controller;
import com.zjy.knife4j.inte.Limit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/ratelimiter")
@RestController
public class RateLimiterController {
    /**
     * 开启限流
     * @return
     */
    @GetMapping("/open")
    @Limit(limitNum = 1, name = "test1")
    public String openRateLimiter1() {
        System.out.println("【限流执行了....编写业务....】");
        return "限流执行了";
    }
    /**
     * 开启限流
     * @return
     */
    @GetMapping("/open2")
    @Limit(limitNum = 1, name = "test2")
    public String openRateLimiter2() {
        System.out.println("【限流执行了222】");
        return "限流执行了222";
    }
    /**
     * 未开启限流
     * @return
     */
    @GetMapping("/close")
    public String closeRateLimiter() {
        System.out.println("【不限流执行了】");
        return "不限流执行了";
    }
}

コードを貼り付けた後、テストを開始します

サービスを開始し、現在の制限アノテーションを追加するインターフェイスにアクセスします

##注釈のないインターフェイスに再度アクセスします

Springboot を使用して RateLimiter 電流制限を統合する方法

コンソールに結果が表示されます:

Springboot を使用して RateLimiter 電流制限を統合する方法

以上がSpringboot を使用して RateLimiter 電流制限を統合する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。