You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Boot REST API请求超时配置问题咨询

给Spring Boot MongoDB查询API添加请求超时的几种方案

针对你这个对外暴露MongoDB数据的REST接口,我整理了几个实用的超时实现方案,你可以根据自己的场景选择:

1. Spring MVC层面直接设置请求超时

这是最简单的方式,直接在控制器的请求映射注解里指定超时时间,到时间后Spring会自动终止请求并抛出超时异常。

修改你的控制器方法注解,加上timeout参数(单位:毫秒):

@RequestMapping(value = "/{coll}", method = RequestMethod.GET, timeout = 5000) // 5秒超时
public List<Map> retrieveMongoData(@PathVariable("collection") String collection , @RequestParam Map<String,String> requestParams) throws Exception{
    Query query = new Query(); 
    // ... 你的查询逻辑
    return mongoTemplate.find(query, Map.class, collection); 
}

注意:这个超时是针对整个HTTP请求的生命周期,不管后端MongoDB查询是否完成,到时间就会触发超时。

2. MongoDB查询层面设置超时

如果你的超时需求主要是针对MongoDB的慢查询,可以直接在Query对象上设置查询超时,让MongoDB服务器主动终止耗时过长的查询,避免占用数据库资源。

在构建Query的时候添加maxTime配置:

@RequestMapping(value = "/{coll}", method = RequestMethod.GET)
public List<Map> retrieveMongoData(@PathVariable("collection") String collection , @RequestParam Map<String,String> requestParams) throws Exception{
    Query query = new Query(); 
    // 设置查询超时为5秒
    query.maxTime(5, TimeUnit.SECONDS);
    // ... 你的查询条件构建逻辑
    return mongoTemplate.find(query, Map.class, collection); 
}

这种方式会让MongoDB在查询超过指定时间后抛出MongoTimeoutException,你可以在全局异常处理器里捕获这个异常,返回合适的HTTP响应(比如408 Request Timeout)。

3. 异步处理+自定义超时控制

如果需要更灵活的超时逻辑(比如超时后执行降级逻辑),可以用Spring的异步支持结合CompletableFuture来实现:

步骤1:开启异步支持

在你的Spring Boot启动类上添加@EnableAsync注解:

@SpringBootApplication
@EnableAsync
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

步骤2:重构查询逻辑为异步方法

可以把MongoDB查询逻辑抽成一个异步方法:

@Service
public class MongoDataService {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Async
    public CompletableFuture<List<Map>> queryDataAsync(String collection, Query query) {
        List<Map> result = mongoTemplate.find(query, Map.class, collection);
        return CompletableFuture.completedFuture(result);
    }
}

步骤3:控制器中调用异步方法并设置超时

@RequestMapping(value = "/{coll}", method = RequestMethod.GET)
public List<Map> retrieveMongoData(@PathVariable("collection") String collection , @RequestParam Map<String,String> requestParams) throws Exception{
    Query query = new Query(); 
    // ... 你的查询条件构建逻辑
    
    // 调用异步方法并设置5秒超时
    CompletableFuture<List<Map>> future = mongoDataService.queryDataAsync(collection, query);
    try {
        return future.get(5, TimeUnit.SECONDS);
    } catch (TimeoutException e) {
        // 超时后的处理逻辑,比如返回空列表或自定义响应
        throw new RequestTimeoutException("查询超时,请稍后重试");
    }
}

额外建议:全局异常处理

不管用哪种方案,建议添加全局异常处理器来统一处理超时异常,返回友好的响应:

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler({RequestTimeoutException.class, MongoTimeoutException.class})
    public ResponseEntity<Map<String, String>> handleTimeoutException(Exception e) {
        Map<String, String> response = new HashMap<>();
        response.put("code", "408");
        response.put("message", e.getMessage());
        return new ResponseEntity<>(response, HttpStatus.REQUEST_TIMEOUT);
    }
}

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

火山引擎 最新活动