2 Aralık 2020 Çarşamba

Servlet 3.0 Asynchronous Request Processing Thread Pool Ayarları

Giriş
Thread Pool Ayarları Spring sürümüne göre değişiyor.

Yeni SpringBoot Kullanıyorsak
Açıklaması şöyle. SpringBoot otomatik olarak bir thread pool yaratıyor.
If you are on Spring Boot 2.1.x or higher a default TaskExecutor will be configured and used for you. However if you have something in your configuration that disables the auto-configuration (like an @EnableWebMvc on an @Configuration class for instance)
Bu thread pool Servlet 3.0 Asynchronous Request Processing - yani  Spring MVC asynchronous request processing için kullanılıyor.  Açıklaması şöyle
In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing.
Ayarlar için SpringAsync application.properties Ayarları yazısına bakınız.

Eski SpringBoot Kullanıyorsak
Açıklaması şöyle. Yani doğru dürüst bir thread pool'u kendimizin ataması gerekiyor.
By default Spring MVC uses a SimpleAsyncTaskExecutor to execute Callable instances returned by controller methods. For production you must replace it with an AsyncTaskExecutor implementation configured appropriately for your environment. The MVC Java config and the MVC namespace both provide options to configure an AsyncTaskExecutor and async request processing in general. You can also configure the RequestMappingHandlerAdapter directly.
Eğer thread pool atamazsak bir uyarı mesajı görürüz. Uyarı mesajı şöyle
An Executor is required to handle java.util.concurrent.Callable return values.
Please, configure a TaskExecutor in the MVC config under "async support".
The SimpleAsyncTaskExecutor currently in use is not suitable under load.
Çünkü SimpleAsyncTaskExecutor her istek için yeni bir thread yaratır. Yani aslında istenen TaskExecutor arayüzünü gerçekleştiren bir sınıf kullanmak. Bu arayüzü gerçekleştiren ve thread pool gibi davranan en uygun sınıf ise ThreadPoolTaskExecutor 

WebMvcConfigurer Arayüzü Yöntemi
Şu satırı dahil ederiz
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
WebMvcConfigurer ile MVC Thread Pool ayarları yapılabilir
Örnek
Şöyle yaparız
@Configuration
public class AsyncConfigurer implements WebMvcConfigurer {

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        configurer.setDefaultTimeout(-1);
        configurer.setTaskExecutor(asyncTaskExecutor());
    }

    @Bean
    public AsyncTaskExecutor asyncTaskExecutor() {
        return new SimpleAsyncTaskExecutor("async");
    }
}
Örnek
Şöyle yaparız. AsyncSupportConfigurer sınıfına kullanmak istediğimiz ThreadPoolTaskExecutor nesnesi atanıyor
@SpringBootApplication
public class SpringAsyncExampleApplication implements WebMvcConfigurer {
 
  @Override
  public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
    configurer.setTaskExecutor(mvcTaskExecutor());
    configurer.setDefaultTimeout(30_000);
  }
 
  @Bean
  public ThreadPoolTaskExecutor mvcTaskExecutor() {
    ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
    taskExecutor.setThreadNamePrefix("mvc-task-");
    return taskExecutor;
  }
}
2. WebMvcConfigurerAdapter Yöntemi
WebMvcConfigurer arayüzünü gerçekleştiren sınıf WebMvcConfigurerAdapter
Örnek
Şöyle yaparız
@Bean
protected WebMvcConfigurer webMvcConfigurer() {
  return new WebMvcConfigurerAdapter() {
    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer c) {
      c.setTaskExecutor(new ConcurrentTaskExecutor(Executors.newFixedThreadPool(5)));
    }
  };
}
Örnek
Şöyle yaparız
@Configuration
@ConfigurationProperties(prefix = "web.executor")
public class CallableConfig {

  public static final int DEFAULT_POOL_SIZE = 2;
  public static final int DEFAULT_QUEUE_SIZE = 2;

  private int minPoolSize = DEFAULT_POOL_SIZE;
  private int maxPoolSize = DEFAULT_POOL_SIZE;
  private int maxQueueSize = DEFAULT_QUEUE_SIZE;

  @Bean
  public AsyncTaskExecutor asyncTaskExecutor() {
    final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(DEFAULT_POOL_SIZE);
    executor.setMaxPoolSize(DEFAULT_POOL_SIZE);
    executor.setQueueCapacity(DEFAULT_QUEUE_SIZE);
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
    executor.setWaitForTasksToCompleteOnShutdown(true);
    return executor;
  }

  @Bean
  public WebMvcConfigurerAdapter webMvcConfigurerAdapter(AsyncTaskExecutor
asyncTaskExecutor) {
    return new WebMvcConfigurerAdapter() {
      @Override
      public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        configurer.setTaskExecutor(asyncTaskExecutor);
super.configureAsyncSupport(configurer);
      }
    };
  }
}
Ayarları da şöyle yaparız
web.executor.minPoolSize=10
web.executor.maxPoolSize=10
web.executor.maxQueueSize=20
3. applicationTaskExecutor Bean'i Yöntemi
İsmi applicationTaskExecutor olan bir bean yaratarak olduğu söyleniyor. Şöyle yaparız
@Bean("applicationTaskExecutor")
public AsyncTaskExecutor executor() {
  ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
  threadPoolTaskExecutor.setThreadNamePrefix("test-");
  threadPoolTaskExecutor.setCorePoolSize(10);
  threadPoolTaskExecutor.setMaxPoolSize(20);
  return threadPoolTaskExecutor;

Hiç yorum yok:

Yorum Gönder