Ich habe eine REST-API, die Spring ThreadPoolTaskExecutor verwendet. Die API sendet abrufbare Jobs intern an ThreadPoolTaskExecutor, der einen Aufruf an einen Dritten tätigt. Sobald der Anruf beendet ist, wird die Geschäftslogik ausgeführt und die Ergebnisse werden an den Anrufer zurückgegeben.Spring: Erstellen eines wirklich skalierbaren Threadpools mit ThreadPoolTaskExecutor
Der Code funktioniert gut, aber wenn die Last steigt, wird die Leistung wirklich schlecht. Ich vermute, dass dies das Ergebnis der Threadpoolgröße für ThreadPoolTaskExecutor ist. Sagen wir also, wenn die gleichzeitigen Benutzer n sind, aber wir nur x Anzahl der Threads haben (x ist kleiner als n), dann muss der x-Thread unnötig auf eine begrenzte Anzahl von Threads warten, um ihre Anfrage zu verarbeiten.
Ich möchte die Third-Party-Aufrufe parallel verarbeiten, aber möchte nicht einen Thread-Pool mit einer großen Anzahl von Threads erstellen.
Optionen für mich ist Executors.newFixedThreadPool (y) zu verwenden. Verwenden Sie es innerhalb der Methode und sobald der Prozess abgeschlossen ist, schließen Sie das Objekt. Dies ist möglich, aber nicht sicher über Nebenwirkungen wie Ist es eine gute Praxis, einen festen Thread-Pool aus der Methode zu erstellen.
Eine andere Option könnte darin bestehen, eine Art Objektpool wie GenericObjectPoolConfig zu verwenden und damit die Threads abzurufen.
Eine andere Option könnte sein, die maximale Poolgröße auf Integer.max zu setzen und die Warteschlangenkapazität auf 1 zu reduzieren. So wird jedes Mal, wenn eine neue Anfrage kommt und das Objekt in der Warteschlange gespeichert wird, ein neuer Thread erstellt.
Es wird hilfreich sein, wenn jemand seine Gedanken teilen kann.
@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;
}
Vielleicht ist der erste Schritt für Ihre ist, einige Instrumente zu tun und zu bestätigen, ob Ihr Verdacht richtig ist - _Ich vermute, dass dies das Ergebnis der Thread-Pool-Größe_ ist.Sie können sich Lösungen ansehen, nachdem Sie bestätigt haben, was der Engpass ist. – jay
Thread-Pool-Größe ist der Grund. Erhöhung der Größe, verbessert die Leistung. – Suchit