Spring Boot 使用 Semaphore 实现外部接口限速和异步调用
使用 Semaphore 实现外部接口限速和异步调用
本文将介绍如何使用 Spring Boot 的 Semaphore 实现外部接口限速,并通过 @Async 注解实现异步调用,确保在并发调用时不超过接口的速率限制。
场景: 假设有一个外部接口,其限制为每秒最多 20 次请求,现在有 5 个方法需要并发调用该接口,每个方法每分钟需要调用 120 次。
解决方案:
- 创建
RateLimiter类: 该类使用Semaphore实现限速功能。
import java.util.concurrent.Semaphore;
public class RateLimiter {
private Semaphore semaphore;
public RateLimiter(int maxPermits) {
semaphore = new Semaphore(maxPermits);
}
public void acquire() throws InterruptedException {
semaphore.acquire();
}
public void release() {
semaphore.release();
}
}
- 在 Spring Boot 配置类中创建
RateLimiter的 Bean:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public RateLimiter rateLimiter() {
return new RateLimiter(20);
}
}
- 创建包含外部接口调用逻辑的服务类:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class ExternalService {
@Autowired
private RateLimiter rateLimiter;
@Async
public void callExternalApi() throws InterruptedException {
rateLimiter.acquire();
// 调用外部接口的逻辑
// ...
rateLimiter.release();
}
}
- 创建定时任务类,每分钟并发调用 5 个方法:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTask {
@Autowired
private ExternalService externalService;
@Scheduled(fixedRate = 60000) // 每分钟执行一次
public void execute() throws InterruptedException {
for (int i = 0; i < 5; i++) {
externalService.callExternalApi();
}
}
}
工作流程:
- 每个方法在调用外部接口之前会先调用
rateLimiter.acquire()获取令牌。 - 如果令牌数量足够,则方法可以继续执行;否则,方法会等待直到获得令牌。
- 在方法执行完成后,调用
rateLimiter.release()释放令牌,以便其他方法可以获取。 - 定时任务每分钟会并发调用 5 个方法,确保每个方法在调用外部接口之前都会进行限速。
注意:
Semaphore的初始值 (即maxPermits) 需要根据外部接口的速率限制进行设置。- 每个方法在调用外部接口后都需要释放令牌,否则会造成令牌不足,导致其他方法无法获取令牌。
- 在实际应用中,可以根据需要调整
@Scheduled注解的fixedRate属性,以及每个方法的调用次数。
通过以上步骤,即可使用 Semaphore 实现外部接口限速,并通过 @Async 注解实现异步调用,确保在并发调用时不超过接口的速率限制。
原文地址: https://www.cveoy.top/t/topic/pbQ9 著作权归作者所有。请勿转载和采集!