探索Java中的限制

2024年 1月 2日 51.5k 0

在软件开发领域,有效管理资源消耗和确保公平使用服务是构建可扩展且健壮的应用程序的重要考虑因素。节流是控制某些操作执行速率的做法,是实现这些目标的关键机制。在本文中,我们将深入探讨在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);
}
}

登录后复制

在此示例中,该类允许每秒执行指定数量的操作。如果操作之间经过的时间小于配置的时间间隔,则会引入睡眠持续时间以达到所需的速率。SimpleRateLimiter

等待的基本限制

让我们从一个简单的示例开始,我们用它来限制方法的执行。目标是允许仅在经过特定冷却时间后调用该方法。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 的类可以用作节流的强大工具。信号量维护一组许可证,其中每个获取操作消耗一个许可证,每个释放操作增加一个许可证。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();
}
}
}

登录后复制

在此示例中,该类使用具有指定数量许可的 a。该方法尝试获取许可证,并在成功时允许该操作。SemaphoreRateLimiterSemaphorethrottle

盒子里的多个例子

Spring 或 Redis 等框架提供了多种简单的解决方案。

Spring AOP 用于方法限制

使用 Spring 的面向方面的编程 (AOP) 功能,我们可以创建一个方法级限制机制。这种方法允许我们拦截方法调用并应用限制逻辑。

@Aspect
@Component
public class ThrottleAspect {

private Map 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 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中的限制的详细内容,更多请关注每日运维网(www.mryunwei.com)其它相关文章!

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论