我暴露了 2 個 api
/endpoint/A 和/endpoint/B 。
@GetMapping("/endpoint/A")
public ResponseEntity<ResponseA> controllerA() throws InterruptedException {
ResponseA responseA = serviceA.responseClient();
return ResponseEntity.ok().body(responseA);
}
@GetMapping("/endpoint/B")
public ResponseEntity<ResponseA> controllerB() throws InterruptedException {
ResponseA responseB = serviceB.responseClient();
return ResponseEntity.ok().body(responseB);
}
關于端點 A 內部呼叫/endpoint/C 和端點 B 內部呼叫/endpoint/D實作的服務。
由于外部服務/endpoint/D需要更多時間,即從/endpoint/A獲得回應需要更多時間,因此整個執行緒都被卡住了,這會影響 /endpoint/B。
我嘗試使用具有以下實作的執行器服務來解決這個問題
@Bean(name = "serviceAExecutor")
public ThreadPoolTaskExecutor serviceAExecutor(){
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(100);
taskExecutor.setMaxPoolSize(120);
taskExecutor.setQueueCapacity(50);
taskExecutor.setKeepAliveSeconds(120);
taskExecutor.setThreadNamePrefix("serviceAExecutor");
return taskExecutor;
}
Even after implementing this if I received more than 200 request on /endpoint/A simultaneously (greater than default max number of threads in Tomcat server) then I am not getting responses from /endpoint/B as all threads are busy for getting response from endpoint A or in queue.
Can someone plz suggest is there any way to apply bucketization on each exposed endpoint level and allow only limited request to process at a time & put remaining into bucket/queue so that request on other endpoints can work properly ?
Edit:- following is solution approach
@GetMapping("/endpoint/A")
public CompletableFuture<ResponseEntity<ResponseA>> controllerA() throws InterruptedException {
return CompletableFuture.supplyAsync(()->controllerHelperA());
}
@GetMapping("/endpoint/B")
public CompletableFuture<ResponseEntity<ResponseB>> controllerB() throws InterruptedException {
return CompletableFuture.supplyAsync(()->controllerHelperB());
}
private ResponseEntity<ResponseA> controllerHelperA(){
ResponseA responseA = serviceA.responseClient();
return ResponseEntity.ok().body(responseA);
}
private ResponseEntity<ResponseB> controllerHelperB(){
ResponseB responseB = serviceB.responseClient();
return ResponseEntity.ok().body(responseB);
}
uj5u.com熱心網友回復:
Spring MVC 支持 Servlet API 3.0 中引入的異步 servlet API。當您的控制器回傳時更容易Callable,CompletableFuture否則DeferredResult它將在后臺執行緒中運行并釋放請求處理執行緒以進行進一步處理。
@GetMapping("/endpoint/A")
public CompletableFuture<ResponseEntity<ResponseA>> controllerA() throws InterruptedException {
return () {
return controllerHelperA();
}
}
private ResponseEntity<ResponseA> controllerHelperA(){
ResponseA responseA = serviceA.responseClient();
return ResponseEntity.ok().body(responseA);
}
現在這將在后臺執行緒中執行。根據您的 Spring Boot 版本,如果您已經配置了自己的版本TaskExecutor,它將要么
- 使用
SimpleAsycnTaskExecutor(這將在您的日志中發出警告), - 提供的默認值
ThreadPoolTaskExecutor,可通過spring.task.execution命名空間進行配置 - 使用您自己的
TaskExecutor,但需要額外的配置。
如果您沒有自TaskExecutor定義定義并且使用的是相對較新的 Spring Boot 2.1 或更高版本 (IIRC),您可以使用以下屬性來配置TaskExecutor.
spring.task.execution.pool.core-size=20
spring.task.execution.pool.max-size=120
spring.task.execution.pool.queue-capacity=50
spring.task.execution.pool.keep-alive=120s
spring.task.execution.thread-name-prefix=async-web-thread
通常這將用于在后臺執行 Spring MVC 任務以及常規@Async任務。
如果您想明確配置TaskExecutor用于 Web 處理的內容,您可以創建一個WebMvcConfigurer并實作該configureAsyncSupport方法。
@Configuration
public class AsyncWebConfigurer implements WebMvcConfigurer {
private final AsyncTaskExecutor taskExecutor;
public AsyncWebConfigurer(AsyncTaskExecutor taskExecutor) {
this.taskExecutor=taskExecutor;
}
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setTaskExecutor(taskExecutor);
}
}
您可以使用@Qualifier建構式引數來指定TaskExecutor要使用的引數。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/437703.html
標籤:multithreading spring-boot spring-mvc tomcat threadpool
上一篇:SpringBoot中的回圈參考
