본문 바로가기
교육/빗썸 테크 아카데미

[빗썸테크아카데미] 두번째 - 블로킹/논블로킹, Reactive System

by 디토20 2022. 4. 13.
반응형

 

[빗썸테크아카데미] 두번째 - 블로킹/논블로킹, Reactive System

 

 

 

지금은 새벽 5시 54분...

월요일에 첫 수업을 듣고 나서 화요일에 마침 휴가라 아침 일찍 일어나서 복습겸 글을 작성했다.

블로그에 정리하는 시간을 확인해보니 거의 세시간이 걸렸던것 같아서

오늘은 원래 평소에 일어나는 시간인 8시보다 두시간 일찍 일어났다.

 

블로그 다 쓰고 출근해야지..!

 

 

 

https://be-developer.tistory.com/37?category=1091769 

 

[빗썸테크아카데미] 첫번째 - OT, 동기/비동기와 Event-driven Architecture

[빗썸테크아카데미] 첫번째 - OT, 동기/비동기와 Event-driven Architecture https://be-developer.tistory.com/34 < (+기술과제)" data-og-description="[빗썸 테크 아카데미] BE 심화 과정 최종 합격 후기..

be-developer.tistory.com

 

 


 

복습 퀴즈

Event Driven Architecture를 설계할 때 고려해야 할 점?

 

 

 

1. Blocking VS Nonblocking

 

1.1 블로킹 vs 논블로킹

블로킹
  • caller가 제어권을 callee에게 넘겨서, callee가 종료될 때까지 실행 정지
  • ex) DB작업 : 데이터 작업을 하는 동안 함수는 정지됨

 

논블로킹
  • caller가 callee를 호출할 때 제어권을 넘기지 않아서 별도로 실행
  • ex) Logging : 중간중간 로그를 찍지만, 로그를 찍던 말던 내 할일을 함

 

 

1.2 동기/비동기 vs 블로킹/논블로킹

동기/비동기
  • caller가 callee의 작업 완료 여부를 확인하는지에 초점
  • 동기는 caller가 callee의 작업 완료 여부를 확인
  • 비동기는 caller가 callee의 작업 완료 여부를 신경쓰지 않음

 

블로킹/논블로킹
  • caller가 callee를 호출하는 시점에 제어권을 넘겨주는지에 대한 시점

 

 

1.3 동기/비동기 & 블로킹/논블로킹의 네가지 조합

동기 & Blocking

func B가 func A를 call 하면, func B는 func A의 작업이 완료되어 return 될때까지 아무것도 못하고 리턴만 기다리다가, func A가 리턴되면 그 이후의 작업을 진행

 

동기 & NonBlocking

func B가 func A를 call 하면, func B는 func A의 작업이 완료되어 return 될때까지 본인 할일을 하면서 func A의 작업이 완료 되었는지 주기적으로 계속 확인을 하다가, func A가 리턴되면 그 이후 func A를 신경쓰지 않음.

 

비동기 & Blocking

func B가 func A를 call 하면, func B는 func A의 작업이 완료되어 return 될때까지 아무것도 못하고 멈춰있다가, func A가 완료되면 그 이후의 작업을 진행. 사실상 쓰이지 않는 코드

 

비동기 & Nonblocking

func B가 func A를 call 할 때 callback 함수를 같이 준 뒤, func B는 func A의 작업의 완료를 신경쓰지 않고 자기 할일을 함. func A가 완료되면 callback 함수를 실행하는데 callback함수는 func A가 될수도 있고, 아예 다른 func C가 될 수도 있음. -> Reactive System은 이 방식을 가장 많이 사용

 

 

 

 

2. Reactive System

2.1 Reactive System이 나온 이유

시스템이 복잡해지면서 요구사항의 변화가 생김

 

1 단계 : 모놀리식 아키텍쳐
  • 한개의 거대한 App
  • 시스템이 복잡하지 않음
  • 모니터링이 용이
  • 개발자의 숙련도가 크게 요구되지 않음
  • 요청량이 많아지면 뻗기 쉬움
  • 한곳에서 뻗으면 장애가 전체적으로 전파되기 쉬움

 

2단계 : 마이크로서비스 아키텍쳐 (MSA)
  • 도메인 별로 나뉘어진 여러개의 Micro App
  • 장애가 나도 다른 시스템으로 장애 전파 X
  • 요청이 많은 시스템은 큰 인프라 할당, 요청이 작은 시스템은 작은 인프라 할당

 

3단계 : 리액티브 프로그래밍
  • 요청이 더더더 발생해서 MSA로도 부족하다! 
  • 응답이 잘 되고, 탄력적이며 유연하고 메세지 기반으로 동작하는 시스템 필요
  • 서로가 서로를 신경쓰지 않고 메세지 기반으로 동작하는 시스템

 

 

 

 

2.2 리액티브 선언문

https://www.reactivemanifesto.org/ko

 

리액티브 선언문

탄력성(Resilient): 시스템이 장애 에 직면하더라도 응답성을 유지 하는 것을 탄력성이 있다고 합니다. 탄력성은 고가용성 시스템, 미션 크리티컬 시스템에만 적용되지 않습니다. 탄력성이 없는 시

www.reactivemanifesto.org

 

응답성

요청자가 요청을 보내면 뭐라도 대답을 보내야한다. 이것을 만족시키기 위해 퍼블리셔는 이벤트 버스에 이벤트를 적재하고, 이벤트의 처리완료까지 기다리지 않고, 이벤트를 잘 적재하였습니다 와 같은 응답을 먼저 보냄.

 

탄력성

요청이 들어오면 실패를 했을때, 모든 시스템에 장애를 전파하지 않고, 즉각 다른 메세지를 처리하도록 패스를 하는 등의 장애 대비 처리를 함. 자가복구가 잘 됨. 

 

유연성

사용량에 대해 유연하게 대응을 할 수 있어야 함.

 

메시지 기반

응답성을 확보하기 위한 도구중 하나. 요청을 보낸 사람은 요청을 보냈다는 것만 알면 되고, 받는 사람은 받는 내용만 알면 된다. 요청을 보내는 사람은 누가 받았는지, 받는사람은 누가 보냈는지에 대해서는 관심 X

 

 

2.3 Reactive Programming

2.3.1 리액티브 프로그래밍이란?

  • 데이터 흐름과 변화 전파에 중점을 둔 프로그래밍 패러다임
  • 데이터 스트림에 데이터가 흘러가면, 내가 관심있는 데이터만 처리를 하는 로직
  • 프로그램 안에서 정적이거나 동적인 데이터 흐름이 표현되어야 함.
  • 데이터 흐름에 따라 하위 로직에 자동으로 변화를 전파할 수 있어야 함.
  • 필수적인 도구로 함수형 프로그래밍이 사용

 

마블 다이어그램

 

 

Thread 1에서 관찰가능한 데이터가 흘러가다가 우리가 처리하고 싶은 데이터를 만나면, Scheduler 부분에서 처리하고 싶은 뭔가의 일을 한 뒤, Thread 2로 컨슈머가 사용할 수 있는 데이터로 뱉어냄.

이때 Thread 1과 2는 같은 Thread 일수도 있고, 다른 Thread 일 수도 있음.

 

 

 

2.4 Marble Diagram

  • 위쪽 관찰가능한 데이터의 스트림이 지나가는 타임라인
  • 플로우는 항상 왼쪽에서 오른쪽으로 흐른다.
  • 각 도형은 이벤트들
  • 제일 오른쪽 버티컬 라인은 끝났다는 컨플릭트
  • 가운데 flip은 뒤집어주세요라는 동작(processor)
  • 아래쪽 스트림에는 processor를 거쳐서 새로 생성된 데이터들

 

 

 

 

2.5 Reactive stream

  • 리액티브 프로그래밍을 위한 인터페이스
  • Nonblocking backpressure를 이용한 비동기 스트림 처리의 표준

 

2.5.1 Reactive Stream 인터페이스

Processor
  • 연산을 하는 연산자들이 모여있는 곳
  • ex) add, max, min 등이 모여있는 곳

 

Publisher
  • 어제 나왔던 개념과 동일! 데이터를 퍼블리싱 하는 것. 

 

Subscriber
  • 4개의 상태 함수를 갖고 있음.
  • onSubscribe : 이 subscriber가 어떤 쓰레드에서 동작을 할 지 결정
  • onNext : 퍼블리싱이 될때 마다 next라는 이벤트를 발생시키는데, 이 next를 잡는 행위
  • onError : 데이터에 발생된 에러를 잡는 것
  • onComplete : 구독중인 스트림이 데이터를 다 방출하면 complete를 실행시키는데, 이 complete를 잡는 함수

 

Subscription
  • 어떤 이벤트를 구독할지 정의하는 기능

 

2.6 Reactor

  • 리액티브 스트림의 구현체 중 하나
  • 스프링 5부터 사용 가능

 

Sequence란
  • 변화 가능한 데이터의 흐름, 데이터의 덩어리
  • Publisher에 의해 Publish 되고 subscriber에 의해 subscription 된다.

 

2.6.1 Reactor core feature

  • Reactor project의 주요 구현체 포함
Mono

  • Publisher의 구현체
  • 비동기 item
  • 0 ~ 1 개의 아이템을 가짐

 

Flux

  • Publisher의 구현체
  • 비동기 Sequence
  • 0 ~ N 개의 아이템을 가짐

 

Schedulers
  • 오퍼레이터를 처리할 쓰레드를 지정해주는 것
  • Reactor는 비동기 실행을 강제하지 않음
  • 따로 쓰레드를 지정해주지 않으면, 메인 쓰레드에서 일을 진행
  • publishOn : 신호 처리 스케쥴링. next, complete, error 신호가 발생할때 쓰레드를 분리 시키라는 함수. 다음 publishOn을 만날 때까지 같은 쓰레드에서 동작.
  • subscribeOn : 구독 처리 스케쥴링. 프로세싱 할 쓰레드를 분리시키라는 함수. publishOn을 만날 때까지 같은 쓰레드에서 동작. publishOn 뒤에 오는 subscribeOn은 무시됨

Schduler 종류

  • Immediate : 지금 실행 중인 쓰레드에서 실행. 딱히 표기 필요 X
  • Single : Runnable Executor 실행
  • Elastic : 쓰레드 무한 생성 하면서 실행
  • Parallel : Core 갯수만큼의 쓰레드 생성
  • BoundedElastic : Core * 10 만큼의 쓰레드 생성. Parallel을 보완하면서 Elastic의 위험성을 낮춤

 

Errors

에러를 다룸

 

Processors

각종 연산자들

 

 

 

2.7 Operators

 

 

 

2.7.1 변환 연산자

 

 

 

2.7.2 필터 연산자

 

 

 

2.7.3 결합 연산자

 

 

2.7.4 오류 처리 연산자

 

 

 

2.7.5 유틸리티 연산자

 

 

2.7.6 조건 연산자

 

 

 

2.7.7 집계 연산자

 

 

 

 

 

*operator들은 평소에 stream에서 자주 사용하는 애들이기 때문에 따로 설명은 안적었다.

▼더 많은 operator들이 궁금하다면 아래 링크에서 확인 ▼*

 

https://reactivex.io/documentation/operators/merge.html

 

 

ReactiveX - Merge operator

RxScala implements this operator as flatten, flattenDelayError, merge, and mergeDelayError. merge takes a second Observable as a parameter and merges that Observable with the one the merge operator is applied to in order to create a new output Observable.

reactivex.io

 

 

 

2.8 Handling errors

  • Publisher가 아이템 처리시마다 onNext() 이벤트를 발생시키다가, error를 만날 경우 onError()를 발생시키고 sequence 중지.
  • onErrorReturn(), onErrorResume() 등으로 error 발생 시 로직 작성 -> try catch랑 똑같음

 

 

2.9 Testing

  • reactor-test dependency 추가
  • 테스트할 모듈이 flux나 mono를 반환하도록 하여 검사
  • 기대하는 동작을 stepVerifier API로 작성

 

1. StepVeritier를 생성해서 테스트할 시퀀스 입력

2. expect*에 다음에 발생할 기대값 표현

3. 일부 시퀀스를 통과하고 싶을 때는 consumeNextWith(Consumer<T>)

4. 종료 이벤트를 기대할 경우 expectComplete(), 혹은 expectError()

5. 마지막으로 verify()를 호출하여 검증 단계 trigger

 

단계 중 기대한 값과 다른 데이터를 subscribe 하면 즉시 AssertionError 발생하며 테스트 종료

 

 


 

 

수업 시간 중 퀴즈

더보기

1. Sequence란?

2. Scheduler, Publisher, Subscriber란?

 

수업에서는 Reactive System 좀 하다가, Blocking 좀 하다가, 다시 Reactive로 넘어왔는데, 글을 정리하다 보니 조금 왔다갔다 하는것 같아서, 내가 임의로 순서를 바꿔서 정리했다.

 

오늘 완전 처음 듣는 개념이 많아서 수업시간 내내 진짜 뭔소린지... 모르겠구.... 이해를 거의 못했는데,

지금 블로그 글 쓰면서 복습하니 정리가 90%정도 된것 같다!

역시 글로 쫙 쓰는게 정리하기 참 좋은 것 같다.

 

일단 출근해야 하니 여기까지 쓰고, 이따 수업 시작하기 전에 다시 한번 더 복습해야겠다.

 

728x90
반응형

댓글