Spring Boot限制控制器中特定API的并发调用数

时间:2018-12-03 18:26:33

标签: java spring-boot

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

由于get user details api的重量很轻,因此登录活动比较繁琐。

我有一个与此类似的控制器

@RestController
public class UserController{

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

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

}

有什么办法可以限制对/login api的并发调用次数。基本上,我想将其限制为x,因为/users/{id}可以在大约10倍的调用中使用相同的资源。

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

1 个答案:

答案 0 :(得分:1)

有些解决方案会限制活动连接的数量,请参见例如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))来限制并发工作,并将您的请求正文提交到该线程池,然后立即调用get on返回的Future。

因此您可以替换

@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上具有某种超时功能,或者将两者结合使用(这对并发会话数也有较大的限制)。