사용자 도구

사이트 도구


springframework:async

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

양쪽 이전 판 이전 판
다음 판
이전 판
springframework:async [2018/07/30 17:41]
kwon37xi [설정]
springframework:async [2023/01/26 10:20] (현재)
kwon37xi [ThreadPoolTaskExecutor 설정]
줄 2: 줄 2:
   * [[http://www.baeldung.com/spring-async|Spring Async]]   * [[http://www.baeldung.com/spring-async|Spring Async]]
   * [[https://docs.spring.io/spring/docs/4.1.x/javadoc-api/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.html|ThreadPoolTaskExecutor]]로 비동기 코드 실행   * [[https://docs.spring.io/spring/docs/4.1.x/javadoc-api/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.html|ThreadPoolTaskExecutor]]로 비동기 코드 실행
 +  * [[java:concurrent:executorservice|Java ExecutorService]]
 +  * 비동기 작업시 [[springframework:bean_lifecycle|Spring Framework Bean Lifecycle]]에 있는 ''SmartLifeCycle''을 구현해줘야만 한다.
  
 ===== 설정 ===== ===== 설정 =====
 +  * Java 8 이후 버전에서는 [[https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/AsyncConfigurer.html|AsyncConfigurer]] interface를 구현하면 된다. default method 라서 원하는 것만 선택구현가능함.
 <code java> <code java>
 @EnableAsync @EnableAsync
줄 19: 줄 22:
  
 ===== ThreadPoolTaskExecutor 설정 ===== ===== ThreadPoolTaskExecutor 설정 =====
-  * [[java:concurrent:executorservice|Java ExecutorService]] 참조 +  * [[java:concurrent:executorservice|Java ExecutorService]] 참조 Spring 의 ThreadPool 
-  * wait 설정으로 서버 종료시 남은 작업을 기다릴 시간 확보+  * wait 설정으로 서버 종료시 남은 작업을 기다릴 시간 확보해야함. 아래를 안해주면 서버가 그냥 종료 돼 버린다.
   * ''waitForTasksToCompleteOnShutdown=true''   * ''waitForTasksToCompleteOnShutdown=true''
   * ''awaitTerminationSeconds=초''   * ''awaitTerminationSeconds=초''
 +  * ''beanName''을 지정해주면 로그에 이름이 찍힘.
 +  * [[https://github.com/kwon37xi/java-spring-thread-pool-test|kwon37xi/java-spring-thread-pool-test: Java와 SpringFramework 의 Thread Pool 작동 방식 테스트]]
 +    * fixed? cached?
 +  * 서버 종료시 올바로 종료됨을 보장하려면 [[springframework:bean_lifecycle|Spring Framework Bean Lifecycle]] [[https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/SmartLifecycle.html|SmartLifeCycle]]도 구현해야한다.
  
 ===== Cached Thread Pool 효과 ===== ===== Cached Thread Pool 효과 =====
-  * QueueCapacity를 0으로 만들면 Cached Thread Pool 처럼 작동한다. +  * corePoolSize 는 적게 혹은 0, maxPoolSize=''Interger.MAX_VALUE'', queueCapacity를 0으로 만들면 Cached Thread Pool 처럼 작동한다. 
   * 기본 CorePoolSize 만큼 풀을 생성하고,   * 기본 CorePoolSize 만큼 풀을 생성하고,
-  * 필요하면 쓰레드풀을 최대 MaxPoolSize 만큼 증가시키고+  * 필요하면 쓰레드풀을 최대 maxPoolSize 만큼 증가시키고
   * 안 사용하는 시간이 KeepAliveSeconds가 지나면 쓰레드를 없앤다.   * 안 사용하는 시간이 KeepAliveSeconds가 지나면 쓰레드를 없앤다.
 +  * cachedThreadPool 은 느려지는 태스크 실행시 쓰레드 갯수가 폭증해서 시스템을 다운시킬 수도 있다.
  
 <code java> <code java>
 ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor(); ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
 threadPoolTaskExecutor.setThreadNamePrefix("XXXX-"); threadPoolTaskExecutor.setThreadNamePrefix("XXXX-");
-threadPoolTaskExecutor.setCorePoolSize(10);+threadPoolTaskExecutor.setCorePoolSize(0);
 threadPoolTaskExecutor.setMaxPoolSize(Integer.MAX_VALUE); threadPoolTaskExecutor.setMaxPoolSize(Integer.MAX_VALUE);
 threadPoolTaskExecutor.setQueueCapacity(0); threadPoolTaskExecutor.setQueueCapacity(0);
줄 42: 줄 49:
 </code> </code>
  
 +===== MDC 사용하기 =====
 +  * ''@Async''로 새로 생성된 쓰레드에서 호출자 쓰레드의 [[java:slf4j:mdc|Slf4j MDC]]를 복제하도록 할 수 있다.
 +  * [[https://moelholm.com/2017/07/24/spring-4-3-using-a-taskdecorator-to-copy-mdc-data-to-async-threads/|Spring 4.3: Using a TaskDecorator to copy MDC data to @Async threads]]
 +
 +==== ThreadPoolTaskExecutor 설정에 Decorator 지정 ====
 +<code java>
 +@Override
 +public Executor getAsyncExecutor() {
 +  ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
 +  executor.setTaskDecorator(new MdcTaskDecorator());
 +  executor.initialize();
 +  return executor;
 +}
 +</code>
 +
 +==== MdcTaskDecorator.java ====
 +<code java>
 +class MdcTaskDecorator implements TaskDecorator {
 + 
 +  @Override
 +  public Runnable decorate(Runnable runnable) {
 +    // Right now: Web thread context !
 +    // (Grab the current thread MDC data)
 +    Map<String, String> contextMap = MDC.getCopyOfContextMap();
 +    return () -> {
 +      try {
 +        // Right now: @Async thread context !
 +        // (Restore the Web thread context's MDC data)
 +        if (contextMap != null) {
 +            MDC.setContextMap(contextMap);
 +        }
 +
 +        runnable.run();
 +      } finally {
 +        MDC.clear();
 +      }
 +    };
 +  }
 +}
 +</code>
 +
 +
 +===== CompletableFuture 지원 =====
 +  * [[java:8:completable_future|Java 8 CompletableFuture]]
 +  * [[https://www.javacodegeeks.com/2016/04/spring-async-javas-8-completablefuture.html|Spring Async and Java's 8 CompletableFuture]]
 +  * [[https://spring.io/guides/gs/async-method/|Getting Started | Creating Asynchronous Methods]]
 +  * [[https://dzone.com/articles/spring-boot-async-methods|Spring Boot - Async methods - DZone Java]]
 +
 +  * 아래와 같이 ''CompletableFuture.completedFuture()''를 리턴하게 만들면 Spring 이 내부적으로 [[https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/aop/interceptor/AsyncExecutionInterceptor.html|AsyncExecutionInterceptor]]에서 진짜 ''CompletableFuture.supplyAsync''로 변환해서 리턴한다. [[https://github.com/spring-projects/spring-framework/blob/master/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java|AsyncExecutionAspectSupport.java 소스]] [[https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/concurrent/ListenableFuture.html|ListenableFuture]]와 [[https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html|Future]]도 마찬가지로 작동함.
 +<code java>
 +@Async
 +public CompletableFuture<User> findUser(String user) throws InterruptedException {
 +    logger.info("Looking up " + user);
 +    String url = String.format("https://api.github.com/users/%s", user);
 +    User results = restTemplate.getForObject(url, User.class);
 +    Thread.sleep(1000L);
 +    return CompletableFuture.completedFuture(results); //IT IS completedFuture
 +}
 +</code>
springframework/async.1532940082.txt.gz · 마지막으로 수정됨: 2018/07/30 17:41 저자 kwon37xi