首页 > 解决方案 > Spring boot 限制控制器中特定 API 的并发调用次数

问题描述

我有一个基于 sprint boot (v1.5.15) 的 Restful 应用程序,它提供基于用户的服务,特别是登录和获取用户详细信息。

登录活动稍微繁重,因为获取用户详细信息 api 的重量很轻。

我有一个类似于这个的控制器

@RestController
public class UserController{

    @PostMapping("/login")
    public LoginResponse userLogin(@RequestBody LoginRequest loginRequest){
        ...
    }

    @GetMapping("/users/{id}")
    public LoginResponse userIdGet(@PathVariable("id") String id){
        ...
    }

}

有什么办法可以限制对/loginapi 的并发调用数。基本上我想限制这个说 x 因为/users/{id}可以处理大约 10 倍的调用的相同资源。

该应用程序使用嵌入式 tomcat 服务器,我知道server.tomcat.max-connections,但是这些限制在应用程序级别而不是 API 上的调用。server.tomcat.max-threadsserver.tomcat.min-spare-threads

标签: javaspring-boot

解决方案


有一些解决方案可以限制活动连接的数量,请参见https://dzone.com/articles/how-to-limit-number-of-concurrent-user-session-in

但是,afaik,这样的解决方案只是拒绝进一步的请求。

如果您不喜欢拒绝请求,您可能会通过使用应用程序范围的固定线程池 ExecutorService ( https://docs.oracle.com/javase/7/docs/api/java/util/concurrent /Executors.html#newFixedThreadPool(int))并将您的请求正文提交到该线程池并立即在返回的 Future 上调用 get 。

所以你可以更换

@PostMapping("/api/xyzMethod")
public Response xyzMethod(@RequestBody Request request) {
    return handleXyzMethod(request); });
}

经过

@PostMapping("/api/xyzMethod")
public Response xyzMethod(@RequestBody Request request) throws InterruptedException, ExecutionException {
    return xyzMethodExecutor.submit(() -> { return handleXyzMethod(request); }).get();
}

和一些

private static ExecutorService xyzMethodExecutor = Executors.newFixedThreadPool(10);

一个缺点是用户可能必须等待回复和/或多个请求将填充线程池队列,直到服务变得(太)无响应。因此,也许您必须在 FutureTasks 上为该解决方案赋予某种超时,或者将这两种解决方案结合起来(即对并发会话的数量也有更大的限制)。


推荐阅读