我有一個使用Spring ThreadPoolTaskExecutor的REST API。 API在內部將可調用作業提交給ThreadPoolTaskExecutor,該調用會向第三方發送調用。一旦完成調用,就會執行業務邏輯並將結果返回給調用者。Spring:使用ThreadPoolTaskExecutor創建真正可伸縮的線程池
代碼工作正常,但當負載增加時,性能變得非常糟糕。我懷疑這是ThreadPoolTaskExecutor的線程池大小的結果。所以說,如果併發用戶是n,但我們只有x線程數(x小於n),那麼x線程將不得不等待有限數量的線程來處理它們的請求。
我要處理的第三方調用平行,但不希望創建的線程數量龐大的線程池。
我的選擇是使用Executors.newFixedThreadPool(y)。在方法內部使用它,一旦過程完成關閉對象。這是可能的但不能確定它的副作用,例如從方法創建固定線程池是否是一個好習慣。
其他選項可能是使用某種像GenericObjectPoolConfig對象池,並用它來獲取線程。
其他選擇可能是設置最大池大小,以Integer.max和減少隊列容量爲1。因此,每個新的請求到來,而不是存儲在隊列中的對象時,它會創建一個新的線程。
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(20);
threadPoolTaskExecutor.setMaxPoolSize(Integer.MAX_VALUE);
threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
threadPoolTaskExecutor.setQueueCapacity(1);
threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
threadPoolTaskExecutor.initialize();
如果有人可以分享他的想法將是有益的。
@Configuration
public class TestConfiguration{
@Bean
public ConcurrentTaskExecutor concurrentTaskExecutor() {
ConcurrentTaskExecutor concurrentTaskExecutor = new ConcurrentTaskExecutor();
concurrentTaskExecutor.setConcurrentExecutor(getExecutor());
return concurrentTaskExecutor;
}
private Executor getExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(20);
threadPoolTaskExecutor.setMaxPoolSize(30);
threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
threadPoolTaskExecutor.setQueueCapacity(75);
threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
}
@Service
public class TestServiceImpl{
@Autowired
private ConcurrentTaskExecutor concurrentTaskExecutor;
@Override
@Transactional
public DTO getDTO() {
Callable<TESTDTO> test1Callable = new Test1Callable();
Future<TESTDTO> testDTO1 = concurrentTaskExecutor.submit(test1Callable);
Callable<TESTDTO> test2Callable = new Test2Callable();
Future<TESTDTO> testDTO2 =concurrentTaskExecutor.submit(test2Callable);
Callable<TESTDTO> test3Callable = new Test3Callable();
Future<TESTDTO> testDTO3 =concurrentTaskExecutor.submit(test3Callable);
// Perform logic on DTO's
return DTO;
}
也許你的第一步是做一些儀器,並確認你的懷疑是否正確 - 我懷疑這是線程池size_的結果。確認瓶頸後,您可以查看解決方案。 – jay
線程池大小是原因。增加尺寸,提高性能。 – Suchit