ch17. 리액티브 프로그래밍

    리액티브 프로그래밍의 중요성

    • 빅데이터: 기가 바이트의 데이터 → 페타 바이트 단위의 데이터
    • 다양한 환경: 모바일 디바이스에서 부터 클라우드 기반 클러스터에 이르기까지 다양한 환경에 애플리케이션이 배포됨
    • 사용자 패턴: 사용자는 1년 내내 항상 서비스를 이용할 수 있으며, 밀리초 단위의 응답시간을 기대함

     

    리액티브 프로그래밍: 다양한 시스템과 소스에서 들어오는 데이터 항목 스트림을 비동기적으로 처리하고 합쳐서 해결함

     

    17.1 리액티브 매니패스토

    리액티브 애플리케이션과 시스템 개발의 핵심 원칙을 공식적으로 정의함

    • 반응성(responsive): 빠르고 일정하고 예상가능한 반응 시간을 제공함
    • 회복성(resilient): 장애가 발생해도 시스템은 반응해야 함
    • 탄력성(elastic): 애플리케이션에 작업 부하가 심해지면 자동으로 컴포넌트에 할당된 자원 수를 늘림
    • 메시지 주도(Messge-driven): 비동기 메시지를 전달해 컴포넌트끼리의 통신이 이루어짐. 회복성과 탄력성을 지원하려면 시스템을 구성하는 컴포넌트의 경계를 명확하게 정의해향함. 
      • 회복성: 장애를 메시지로 처리
      • 탄력성: 주고받은 메시지 수를 감시하고 메시지 양에 따라 적절하게 리소스를 할당

     

    17.1.1 애플리케이션 수준의 리액티브 (리액티브 애플리케이션)

    • 주요 기능 비동기로 작업을 수행
    • 이벤트 스트림을 블록하지 않고 비동기로처리하는 것이 멀티코어 CPU의 사용률을 극대화할 수 있음
    • 리액티브 프레임워크 & 라이브러리는 스레드를 이벤트 루프 등과 공유하고, 처리할 이벤트를 관리함. 비동기 애플리케이션 구현의 추상 수준을 높일 수 있으므로 동기 블록, 경쟁 조건, 데드락 같은 저 수준의 멀티스레드 문제를 직접 처리하지 않아도 됨
    • 스레드를 다시 쪼개는 종류의 기술을 사용할 때 메인 이벤트 루프 안에서 동작을 블록하지 않아야 함
      • RxJava, Akka와 같은 리액티브 프레임워크는 별도로 지정된 스레드 풀에서 블록 동작을 실행시켜 문제를 해결함.메인 풀의 모든 스레드는 방해받지 않고 실행되므로 모든 CPU 코어가 가장 최적의 상황에서 동작할 수 있음. CPU 관련 작업과 I/O 관련 작업을 분리하면 더 정밀하게 풀의 크기를 설정할 수 있고, 두 타입의 작업의 성능을 관찰할 수 있음

     

     

    17.1.2 시스템 수준의 리액티브 (리액티브 시스템)

    • 리액티브 시스템
      • 여러 애플리케이션이 하나의 일관적인, 회복 가능한 플랫폼을 구성할 수 있게 함
      • 애플리케이션들 중 하나가 실패해도 전체 시스템은 계속 운영될 수 있도록 도와주는 소프트웨어 아키텍쳐
      • 애플리케이션을 조립하고 상호소통을 조절함. 메시지 주도가 특징임

     

    • 리액티브 어플리케이션
      • 리액티브 시스템을 구현한 어플리케이션
      • 비교적 짧은 시간 도안만 유지되는 데이터 스트림에 기반한 연산을 수행하며 보통 이벤트 주도로 분류됨.
        • 메시지는 정의된 목적지 하나를 향하는 반면, 이벤트는 관련 이벤트를 관찰하도록 등록한 컴포넌트가 수신한다는 점이 다름.

     

    리액티브 시스템

    • 고립&비결합(회복성): 수신자와 발신자가 수신 메시지와 발신 메시지를 결합하지 않도록 이 메시지들을 비동기로 처리해야 함. 각 컴포넌트를 완전히 고립하려면 이들을 결합되지 않도록 해야함. 이를 통해 시스템이 장애와 높은 부하에서도 반응성을 유지할 수 있음
    • 위치 투명성(탄력성): 리액티브 시스템의 컴포넌트들이 물리적인 위치에 대한 정보를 알 필요 없이 서로 통신할 수 있음. 즉, 어떤 컴포넌트가 다른 컴포넌트에게 메시지를 보낼 때, 그 컴포넌트가 물리적으로 어디에 위치해 있는지 몰라도 메시지를 보낼 수 있어야 함. 시스템의 위치 정보가 추상화되어 있기 때문에 시스템을 쉽게 복제할 수 있으며 현재 작업 부하에 따라 자동으로 애플리케이션을 확장할 수 있음

     

     

    17.2 리액티브 스트림과 플로 API

    • 리액티브 프로그래밍: 리액티브 스트림을 사용하는 프로그래밍
    • 리액티브 스트림: 잠재적으로 무한한 비동기 데이터를 순서대로 그리고 블록하지 않는 역압력을 전재해 처리하는 표준 기술
    • 역압력
      • 목적지 스트림에서 처리할 수 있는 양보다 소스 스트림에서 생성되는 양이 더 많을 때 발생.
      • 소스 스트림에서는 목적지 스트림으로 더 이상 데이터를 전송하지 않음
      • 시스템 전체에서 과부하가 발생하는 것을 방지할 수 있음

     

     

    17.2.1 Flow 클래스 소개

    java9의 java.util.concurrent.Flow

    Pub-Sub 모델을 지원할 수 있도록 인터페이스를 제공함

     

    • Publisher
      • 함수형 인터페이스
      • 항목 발행
      • Subscriber의 요구사항에 따라 역압력 기법에 의해 이벤트 제공 속도가 제한됨
    • Subscriber
      • Publisher가 발행한 이벤트 리스너
      • 한 개씩 또는 한 번에 여러 항목을 소비
    • Subscription
      • Publisher와 Subscriber 사이의 제어 흐름, 역압력을 관리
    • Processor

     

    Publisher & Subscriber

    @FunctionalInterface
    public interface Publisher<T>{
    	void subscribe(Subscriber<? super T> s);
    }
    public interface Subscriber<T>{
    	void onSubscribe(Subscription s);
        void onNext(T t);
        void onError(Throwable t);
        void onComplete();
    }
    • 순서를 지켜야함
      • onSubscribe onNext* (onError | onComplete)?
      • onSubscribe → onNext 0~무한번 → 끝나려면 onError or onComplete 중 하나로 끝나기
    • Subscriber가 Publisher에 자신을 등록할 때, Publisher는 onSubscribe 메서드를 호출해서 Subscription 객체를 전달함

     

    Subscription

    public interface Subscription{
    	void request(long n);
        void cancel();
    }
    • Subscription 인터페이스는 메서드 두 개를 정의함
      • request(long n): Publisher에게 n개의 이벤트를 처리할 준비가 되었음을 알림
      • cancel(): Subscription을 취소함. Publisher에게 더 이상 이벤트를 받지 않음을 통지함

     

     

    • Publisher는 반드시 Subscription의 request 메서드에 정의된 개수 이하의 요소만 Subscriber에게 전달해야 함
    • Subscriber는 요소를 받아 처리할 수 있음을 Publisher에 알려야 함 (역압력)
    • Pub-Sub은 정확하게 Subscrption을 공유해야하며 각각이 고유한 역할을 수행해야 함

     

    Processor

    public interface Processor<T,R> extends Subscriber<T>, Publisher<R> {
    
    }
    • Processor interface
      • 리액티브 스트림에서 처리하는 이벤트의 변환 단계를 나타냄
      • Processor가 에러를 수신하면 이로부터 회복하거나 즉시 onError 신호로 모든 Subscriber에게 에러를 전파할 수 있음
      • Subscriber가 Subscription을 취소하면 Processor는 자신의 업스트림 Subscription도 취소하므로 취소 신호를 전파해야함

    댓글