You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot RestController如何限制POST接口单线程执行其余返回429

问题根因

你当前代码的并发问题核心是isProcessAlive()状态判断和execute()执行两个操作不具备原子性,高并发场景下多个线程会同时通过isProcessAlive() == false的校验,全部进入执行逻辑,因此都返回201状态码。

解决方案

你可以用AtomicBoolean的原子CAS操作实现无锁的状态校验,保证同一时间只有一个线程能进入执行逻辑,其余线程直接返回429。

代码修改

首先在Controller类中定义一个原子布尔类型的全局执行标记:

// 类成员变量,默认false代表当前无任务在执行
private final AtomicBoolean taskRunning = new AtomicBoolean(false);

然后修改接口逻辑:

@ResponseStatus(code = HttpStatus.CREATED)
@PostMapping(value ="/myApp",consumes="application/json",produces="application/json")
public Execution execute(@RequestBody ParameterDTO StartDateParameter)  
{
    if(StartDateParameter.getStartDate()==null) {
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
    }
    // 原子操作:仅当标记为false时修改为true,返回true代表拿到执行权限
    if (!taskRunning.compareAndSet(false, true)) {
        throw new ResponseStatusException(HttpStatus.TOO_MANY_REQUESTS);
    }
    try {
        // 可选:保留原有状态判断做二次防护
        if(Executer.isProcessAlive()) {
            throw new ResponseStatusException(HttpStatus.TOO_MANY_REQUESTS);
        }
        return Executer.execute(StartDateParameter);
    } finally {
        // 无论执行成功/报错,最终都要重置标记,避免后续请求一直被拦截
        taskRunning.set(false);
    }
}

注意事项

  • 如果Executer.execute()是异步执行逻辑,不要在接口方法返回时就重置标记,需要等异步任务实际执行完成后再修改taskRunning的值,否则异步任务还在运行就释放了标记,还是会出现并发问题。
  • 以上方案仅适用于单机部署场景,如果你的服务是集群部署,需要替换为分布式锁实现全局的执行状态校验。
  • 不推荐使用synchronized关键字包裹逻辑,该方案会导致后续请求阻塞等待,而非直接返回429,不符合你的需求。

内容的提问来源于stack exchange,提问作者user14857007

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 05:15:03