我有一个基于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-connections
,server.tomcat.max-threads
和server.tomcat.min-spare-threads
,但是这些限制了在应用程序级别而不是API上的调用。
答案 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上具有某种超时功能,或者将两者结合使用(这对并发会话数也有较大的限制)。