Icednut's Note

스프링캠프 2017 첫째날 메모

2017-04-22

들은 세션 목차

  • Keynote
  • 프로세스, 스레드, 리액티브
  • Aync@Spring
  • Spring WebFlux
  • Spring Cloud Data Flow
  • 비동기 어플리케이션과 모니터링으로 밀당하기
  • 그 외

Keynote

  • 히든 피겨스(Hidden Figures)

프로세스, 스레드, 리액티브 (발표자: 부종민)

발표자료: https://docs.google.com/presentation/d/1gIZP1DBTTXnGtIgU1KPD6TWxQlOqZAjFOpE2F_jrNiY/mobilepresent?slide=id.g35f391192_00

  • 프로세스는 프로세스 별로 메모리 공간 관리
  • 멀티프로세스는 컨텍스트 스위칭 시 L1, L2, L3 Cache를 비움
  • Java Internal
  • I/O Blocking 관련된 비지니스는 스레드로 개발한 경우가 많음
  • Java Thread1: Thread Class + Runnable interface (Java Thread는 OS Thread를 사용)
    • 코드의 실행 흐름을 알기 어렵다.
    • Thread의 실행 결과물을 공유하기 어렵다. -> Main Thread에서 Sub Thread의 결과를 받고 싶을땐 어떻게할까? Main Thread에서 HashMap을 만들고 Sub Thread에서 거기에 저장
    • 동기화는? wait(), notify(), syncronized -> 개발자의 실수가 많아짐
    • 구현 Example
  • Java Thread2: Future, Callable
    • 비동기 작업의 결과를 받아오고 싶을 떈 Future Interface의 get()를 사용
    • 구현 Example
    • Executors.newSingleThreadExecutor()
    • Future는 JDK 1.5에서 등장
    • Future만으로도 만족스럽긴 한데 thread를 직접 사용하는건 쉽지 않음 (지식 + 경험 필요), 스레드풀에 대한 지식도 필요
    • ThreadPool 사용 시 트래픽 폭주 시 큐에 스레드가 많이 쌓여서 오히려 속도가 더 안나오는 경우가 있음
    • newCacheThreadPool 사용 시 1 request 처리 시 7 thread가 필요한데 트래픽 폭주 시 스레드가 폭등
  • Java Thread3: CompletableFuture
    • Future 사용 시 콜백 지옥에 빠질 수 있음
    • Future 시리즈 중 끝판왕 interface CompletionStage
    • 구현 Example
    • CompletableFuture는 JDK 1.8 부터 추가됨
    • Task간 순서와 조합을 CompletableFuture를 사용하여 Chaining 방식으로 해결할 수 있음 (CompletableFuture.thenApply(), CompletableFuture.thenCombine(), CompletableFuture.thenApplyAsync())
    • 좋긴한데 이것도 싱글 밸류에 콜백 형태이다. -> Collection에 넣고 CompletableTure를 할 수 없을까?
  • Java NIO
    • 아직 풀지 못한 상황 ThreadPool Full
    • Circuit Breaker를 하다가 NonBlocking으로 해볼 수 있지 않을까?
    • NIO 이전: Native IO의 내용을 JVM Heap에 복사해서 IO
    • NIO 이후: Native IO를 그대로 사용
  • Nonblocking I/O
    • Servlet 3.0: AsyncServlet
    • Servlet 3.1: Nonblocking I/O
  • Event Programming: CF의 공통점 complete로 깨워서 thenApply에서 처리한다. -> 이벤트 드리븐 프로그래밍 방식 아닌가?
    • 이벤트가 발생한다는 전제를 깔고 프로그래밍
    • 이벤트 세상에서 오히여 절차형으로 프로그래밍하는게 어렵다? -> 이벤트 프로그래밍을 위해 잘 추상화된 API -> Reactive Programming, JDK9 Flow
    • 너무 공부할게 많다. -> 범위를 좁혀보자. Java, Spring, Reactive -> Reactive Stream
    • 성능은? -> backpressure valve (배압밸브?) -> Circuit Breaker 패턴과 비슷 (Spring 5 MVC에 포함됨)
  • http://github.com/boojongmin/presentation

Aync@Spring (발표자: 이일민)

  • Spring 3.2 ~ 4.3에서 비동기 개발을 어떻게 할 것인가?
  • 스프링 비동기 개발 기본지식은 뭐가 필요할까?
    • 자바 비동기 개발지식 (Java Thread …)
    • 서블릿 비동기 개발 (Servlet 3.x …)
    • 스프링 비동기 개발 (@Async, AsyncRestTemplate)
  • 동기/비동기를 언급할 때는
    • 뭐랑 뭐가 시간을 맞출 것인가를 기억하자.
    • Sync, Async <-> Blocking, Nonblocking
    • 블로킹, 넌블로킹은 대상이 제한적임 (IO, Multi-Thread)
    • 어떤 것에 대해 비동기 동기냐, 어떤 작업에 대해 블로킹, 넌블로킹이냐로 분리해서 생각해보자.
  • @Async 사용 시 메소드 리턴타입이 String일 때는 null이 반환됨 -> void, Future, ListenableFuture, CompletableFuture를 쓰자. -> new AsyncResult()에 담아서 리턴하자.
    • ListenableFuture: Spring 4.0 부터 추가됨 -> 성공 결과와 오류(Exception) 결과를 따로 나눠서 받을 수 있음
    • CompletableFuture.CompletedFuture(result);
    • @Async를 아무런 설정없이 쓴다면 SimpleAsyncTaskExecutor를 사용함 -> 쓰레드풀이 아니며 실전에서는 사용하지 말자. (단점: @Async를 쓸 때마다 스레드를 새로 만듬, 불릴 떄마다 스레드가 생기므로 1000번 호출하면 스레드 1000개가 생성된다고 보면 됨)
    • ThreadPoolExecutor는 처음엔 큐 사이즈만큼 스레드 실행을 대기하고 CoreSize 만큼 스레드를 생성한다.
  • 비동기 Spring@MVC
    • Servlet 3.0 + Spring MVC 비동기 처리
    • 타임아웃이 필요한 API에는 리턴타입으로 WebAsyncTask을 사용하자.
    • DeferredResult와 @Async를 결합한 것을 스프링이 만들어놓음 -> 리턴타입을 그냥 ListenableFutre로 쓰면 똑같이 동작 -> 콜백 지옥에 빠질 수 있음
    • CompletableFuture를 쓰자 -> CompletionStage의 조합으로 콜백 체이닝으로 표현할 수 있음
  • AsyncRestTemplate (비동기 논블로킹 API 호출)
    • RestTemplate는 API 호출 시 블로킹 됨 -> 쓰레드를 하나 잡고 있는 동기 방식
    • AsyncRestTemplate는 비동기, 논블로킹 방식으로 API 호출 가능
    • 톰캣은 스레드 200개 밖에 안되는데 ART로 100개의 API 호출하면 스레드 100개가 생성된다. 낭비 아닌가? Nonblocking IO를 사용하진 않는다는 뜻
    • 논블로킹 IO를 사용하는 AsyncRestTemplate를 사용해야 함 -> Netty Http Client Factory를 사용하자. (100번 API 호출해도 쓰레드 1개로 처리)
  • 결론
    • 스프링의 모든 비동기 기술에는 ExecutorService의 세밀한 설정이 가능
    • 모르고 쓰면 안됨! 설명할 수 있어야 하고 증명할 수 있어야 한다. (잘 모르고 쓰면 이게 주는 혜택도 뭔지 모를 수 있다.)
    • 디버깅이 좀 힘들 수 있다.

Spring WebFlux (발표자: 이일민)

  • Spring 5.0 WebFlux 소개와 개발 방법
  • 스프링 리액티브 스택의 웹 파트 담당
  • 왜 쓸까? 비동기-논블로킹 리액티브 개발에 사용 (CPU, 자원 낭비 없이 효율적인 고성능 웹앱 개발을 위해)
  • @MVC 스타일로 개발할 수 있지만, Annotation이 없는 웹개발을 진행하게 되며, 서블릿 스택과 API에서 탈피 (서블릿이 지원하는 컨터이너에서 동작은 하지만 서블릿을 쓰는건 아님)
  • 서블릿 스레드를 빨리 반환하게 하는 방식으로 개선 가능
  • WebFlux만으로는 성능이 좋아지지 않는다. 동기-블로킹 방식의 환경일 때는.. -> 그럼 개선사항은?
    • 데이터 액세스 리포지토리: JDK10 에서 AsyncJDBC를 지원할수도…, Spring Data JPA의 리턴타입을 @Async와 CompletableFuture로 사용, MongoDB, Cassandra, Redis를 사용하여 논블로킹 방식으로 데이터를 받아낼 수 있다. (DB부터 Web까지 논블로킹으로 동작하게 할 수 있다.)
    • HTTP API 호출: WebClient를 사용하며, 처음 쓸 떄는 람다로 타입이 가려진채로 쓰지말고 명시적으로 타입이 나온 형태로 코드를 작성해보자.
  • 혜택을 보려면… WebFlux + Reactive Repository, Reactive Remote API call + @Async Block IO을 지원해야 한다.

Spring Cloud Data Flow (발표자: 정윤진)

비동기 어플리케이션과 모니터링으로 밀당하기 (발표자: 이건희)

  • 비동기 어플리케이션 모니터링의 어려움과 어떻게 해결할지에 대해 얘기함
  • CPU는 그대로 응답시간이 올라가고 처리량이 떨어질떈? Restart -> APM으로 성능 메트릭 & 원인 찾기
  • BCI? Byte code instrumentation -> premain(), ASM, Javassist
  • 스레드 덤프를 뜨면 스레드 스택 트레이스의 시작 시간, 파라미터 정보를 보고 싶다. 어떻게? BCI
    • 스레드의 이름을 바꿈 -> 해당 스레드 이름으로 로그를 찾으면되지 않을까?
    • MDC (Logging Framework)
  • Block Multi-thread는 스레드덤프 이해하기가 쉽다. 그 반대는? asyncRestTemplate에 병목이 걸린 경우에는 스레드 덤프에도 안나옴
    • 어떻게 해결? Netflix의 사례를 살펴보자.
    • ThreadLocal을 통해 context 정보를 공유할 수 없음 -> ThreadPool 같이 스레드 재사용 하는 환경에서는 쓸 수 없음
    • Runnable, Callable으로 해서 스레드 로컬로 this를 키값으로 저장
    • Lambda일 때는? 람다는 이너 클래스이긴 하지만 이너 클래스가 아니다. Lambda Proxy -> 람다 바디는 private static method -> 람다의 생성자는 어디며, this는 누구? LambdaMetaFactory!
    • ByteBuddy를 통해 LambdaMetaFactory를 transfrom 한다.

그 외

  • 인텔리제이 > Key Promoter: 버튼이나 메뉴 누르면 단축키 보여주는 플러그인
  • 마젤란홀에서만 있었는데 앞사람 머리 때문에 프리젠테이션이 잘 안보인다..
Tags: spring springcamp