Java の制限を調べる

尊渡假赌尊渡假赌尊渡假赌
リリース: 2024-01-02 10:28:41
転載
1431 人が閲覧しました

ソフトウェア開発の世界では、リソース消費を効果的に管理し、サービスの公正な使用を確保することが、スケーラブルで堅牢なアプリケーションを構築する際の重要な考慮事項です。スロットリングは、特定の操作が実行される速度を制御する実践であり、これらの目標を達成するための重要なメカニズムです。この記事では、Java でスロットルを実装するさまざまな方法を詳しく掘り下げ、実践的な例とともにさまざまな戦略を紹介します。

Java の制限を調べる

Java の制限の調査: 簡単な実装例 - パート 1

リソース消費を効率的かつ確実に管理するサービスの公正な使用は、スケーラブルで堅牢なアプリケーションを構築する際の重要な考慮事項です。

ソフトウェア開発の世界では、リソース消費を効果的に管理し、サービスの公正な使用を確保することが、スケーラブルで堅牢なアプリケーションを構築する際の重要な考慮事項です。スロットリングは、特定の操作が実行される速度を制御する実践であり、これらの目標を達成するための重要なメカニズムです。この記事では、Java でスロットリングを実装するさまざまな方法を詳しく掘り下げ、実践的な例とともにさまざまな戦略を紹介します。

免責事項: この記事では、基本的な解決策を解決する単純なシングルスレッドの図に焦点を当てます。

制限について理解する

制限には、特定の操作の実行を許可する頻度の規制が含まれます。これは、システムを悪用から保護する必要がある場合、リソース管理が必要な場合、または共有サービスへの公平なアクセスが必要な場合に特に重要です。スロットルの一般的な使用例には、API リクエストのレートの制限、データ更新の管理、重要なリソースへのアクセスの制御などが含まれます。

単純なブロッキング レート リミッター - 本番環境では使用できません。 thread.sleep()

スロットリングを実装する簡単な方法は、このメソッドを使用して、連続する操作間に遅延を導入することです。この方法は単純ですが、ブロッキングの性質があるため、高パフォーマンスのシナリオには適さない可能性があります。 Thread.sleep()

public class SimpleRateLimiter {

    private long lastExecutionTime = 0;
    private long intervalInMillis;

    public SimpleRateLimiter(long requestsPerSecond) {
        this.intervalInMillis = 1000 / requestsPerSecond;
    }

    public void throttle() throws InterruptedException {
        long currentTime = System.currentTimeMillis();
        long elapsedTime = currentTime - lastExecutionTime;

        if (elapsedTime < intervalInMillis) {
            Thread.sleep(intervalInMillis - elapsedTime);
        }

        lastExecutionTime = System.currentTimeMillis();
        // Perform the throttled operation
        System.out.println("Throttled operation executed at: " + lastExecutionTime);
    }
}
ログイン後にコピー

この例では、このクラスにより、指定された数の操作を 1 秒あたりに実行できます。操作間の経過時間が設定された間隔より短い場合、目的のレートを達成するためにスリープ期間が導入されます。 SimpleRateLimiter

Wait の基本的な制限

メソッドの実行を制限するために使用する簡単な例から始めましょう。目標は、特定のクールダウン時間が経過した後にのみメソッドを呼び出せるようにすることです。 wait

public class BasicThrottling {

    private final Object lock = new Object();
    private long lastExecutionTime = 0;
    private final long cooldownMillis = 5000; // 5 seconds cooldown

    public void throttledOperation() throws InterruptedException {
        synchronized (lock) {
            long currentTime = System.currentTimeMillis();
            long elapsedTime = currentTime - lastExecutionTime;

            if (elapsedTime < cooldownMillis) {
                lock.wait(cooldownMillis - elapsedTime);
            }

            lastExecutionTime = System.currentTimeMillis();
            // Perform the throttled operation
            System.out.println("Throttled operation executed at: " + lastExecutionTime);
        }
    }
}
ログイン後にコピー

この例では、このメソッドを使用して、クールダウン期間が経過するまでスレッドを待機させます。 throttledOperationwait

待機と通知による動的制限

前の例を拡張して、クールダウンを動的に調整できる動的スロットリングを導入しましょう。プロダクションには、その場で変更を加える機会が必要です。

public class DynamicThrottling {

    private final Object lock = new Object();
    private long lastExecutionTime = 0;
    private long cooldownMillis = 5000; // Initial cooldown: 5 seconds

    public void throttledOperation() throws InterruptedException {
        synchronized (lock) {
            long currentTime = System.currentTimeMillis();
            long elapsedTime = currentTime - lastExecutionTime;

            if (elapsedTime < cooldownMillis) {
                lock.wait(cooldownMillis - elapsedTime);
            }

            lastExecutionTime = System.currentTimeMillis();
            // Perform the throttled operation
            System.out.println("Throttled operation executed at: " + lastExecutionTime);
        }
    }

    public void setCooldown(long cooldownMillis) {
        synchronized (lock) {
            this.cooldownMillis = cooldownMillis;
            lock.notify(); // Notify waiting threads that cooldown has changed
        }
    }

    public static void main(String[] args) {
        DynamicThrottling throttling = new DynamicThrottling();

        for (int i = 0; i < 10; i++) {
            try {
                throttling.throttledOperation();
                // Adjust cooldown dynamically
                throttling.setCooldown((i + 1) * 1000); // Cooldown increases each iteration
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
ログイン後にコピー

この例では、クールダウン時間を動的に調整する方法を紹介します。このメソッドは、待機中のスレッドをウェイクアップして、新しいクールダウン時間を確認できるようにするために使用されます。 setCooldownnotify

Java のセマフォの使用

Java クラスは、調整のための強力なツールとして使用できます。セマフォはライセンスのセットを維持し、取得操作ごとに 1 つのライセンスが消費され、解放操作ごとに 1 つのライセンスが増加します。 Semaphore

public class SemaphoreRateLimiter {

    private final Semaphore semaphore;

    public SemaphoreRateLimiter(int permits) {
        this.semaphore = new Semaphore(permits);
    }

    public boolean throttle() {
        if (semaphore.tryAcquire()) {
            // Perform the throttled operation
            System.out.println("Throttled operation executed. Permits left: " + semaphore.availablePermits());
            return true;
        } else {
            System.out.println("Request throttled. Try again later.");
            return false;
        }
    }

    public static void main(String[] args) {
        SemaphoreRateLimiter rateLimiter = new SemaphoreRateLimiter(5); // Allow 5 operations concurrently

        for (int i = 0; i < 10; i++) {
            rateLimiter.throttle();
        }
    }
}
ログイン後にコピー

この例では、クラスは指定されたライセンス数の を使用します。このメソッドはライセンスの取得を試み、成功すると操作を許可します。 SemaphoreRateLimiterSemaphorethrottle

ボックス内の複数の例

Spring や Redis などのフレームワークは、複数の単純なソリューションを提供します。

メソッド制限のための Spring AOP

Spring のアスペクト指向プログラミング (AOP) 機能を使用すると、メソッド レベルの制限メカニズムを作成できます。このアプローチにより、メソッド呼び出しをインターセプトし、スロットル ロジックを適用することができます。

@Aspect
@Component
public class ThrottleAspect {

    private Map<String, Long> lastInvocationMap = new HashMap<>();

    @Pointcut("@annotation(throttle)")
    public void throttledOperation(Throttle throttle) {}

    @Around("throttledOperation(throttle)")
    public Object throttleOperation(ProceedingJoinPoint joinPoint, Throttle throttle) throws Throwable {
        String key = joinPoint.getSignature().toLongString();

        if (!lastInvocationMap.containsKey(key) || System.currentTimeMillis() - lastInvocationMap.get(key) > throttle.value()) {
            lastInvocationMap.put(key, System.currentTimeMillis());
            return joinPoint.proceed();
        } else {
            throw new ThrottleException("Request throttled. Try again later.");
        }
    }
}
ログイン後にコピー

この例では、カスタム アノテーションと AOP アスペクト() を定義して、 を使用してメソッドをインターセプトし、最後の呼び出しからの経過時間をチェックし、それに応じてメソッドを許可またはブロックします。 @ThrottleThrottleAspect@ThrottleThrottleAspect

Guava RateLimiter の使用

Google の Guava ライブラリは、制限の実装を簡素化するクラスを提供します。これにより、操作が許可されるレートを定義できます。 RateLimiter

メソッド制限にどのように使用できるかを見てみましょう: RateLimiter

import com.google.common.util.concurrent.RateLimiter;

@Component
public class ThrottledService {

    private final RateLimiter rateLimiter = RateLimiter.create(5.0); // Allow 5 operations per second

    @Throttle
    public void throttledOperation() {
        if (rateLimiter.tryAcquire()) {
            // Perform the throttled operation
            System.out.println("Throttled operation executed.");
        } else {
            throw new ThrottleException("Request throttled. Try again later.");
        }
    }
}
ログイン後にコピー

この例では、Guava を使用してメソッドの実行速度を制御します。このメソッドは、定義されたレートに基づいて操作が許可されているかどうかを確認するために使用されます。 RateLimiterthrottledOperationtryAcquire

制限メカニズムとしての Redis

Redis のような外部データ ストアを使用すると、分散調整メカニズムを実装できます。このアプローチは、複数のインスタンスが制約を調整する必要があるマイクロサービス環境で特に役立ちます。

@Component
public class RedisThrottleService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Value("${throttle.key.prefix}")
    private String keyPrefix;

    @Value("${throttle.max.operations}")
    private int maxOperations;

    @Value("${throttle.duration.seconds}")
    private int durationSeconds;

    public void performThrottledOperation(String userId) {
        String key = keyPrefix + userId;
        Long currentCount = redisTemplate.opsForValue().increment(key);

        if (currentCount != null && currentCount > maxOperations) {
            throw new ThrottleException("Request throttled. Try again later.");
        }

        if (currentCount == 1) {
            // Set expiration for the key
            redisTemplate.expire(key, durationSeconds, TimeUnit.SECONDS);
        }

        // Perform the throttled operation
        System.out.println("Throttled operation executed for user: " + userId);
    }
}
ログイン後にコピー

この例では、Redis を使用してユーザーごとの操作数を保存および管理します。このメソッドはカウントを増分し、許可された制限に達したかどうかを確認します。 PerformThrottledOperation

結論

スロットリングは、アプリケーションの安定性とスケーラビリティを維持する上で重要な役割を果たします。この記事では、すぐに使用できるソリューションを使用および適用するための簡単なテクニックを含め、Java でスロットリングを実装するさまざまな方法を検討します。 Thread.sleep()Semaphore

制限戦略の選択は、アプリケーションの性質、パフォーマンス要件、必要な制御レベルなどの要因によって異なります。制限を実装するときは、悪用の防止と、応答性の高い公平なユーザー エクスペリエンスの確保との間でバランスをとる必要があります。

スロットル メカニズムをアプリケーションに統合する場合は、実際の使用パターンに基づいてパラメータを監視および調整することを検討してください。制約の実装を決定する際、タスクが割り当てられた期限を超過した場合の対処方法など、いくつかの疑問が生じることがあります。次回の記事では、さまざまなシナリオに包括的に対処する堅牢な Java 実装について検討する予定です。

以上がJava の制限を調べるの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:dzone.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート