스트림 프로세싱 관련 글

1.스트림 프로세싱 패턴들
2.스트림 프로세싱의 확장성을 확보하고 성능을 최적화하기 위한 패턴들
3.스트림 프로세싱 서버가 터져도 살아남는 법 (aka 신뢰성 확보)

데이터의 홍수 속 실시간 데이터 처리는 다양한 애플리케이션과 의사결정의 도구로 사용되고 있습니다.
오늘은 클라우드 네이티브 애플리케이션에서의 스트림 프로세싱에 대해 알아보고 상황별로 적용할 수 있는 스트림 프로세싱 패턴들에 대해 알아보겠습니다.

스트림이란?

스트림이란 시간 순서에 따라 정렬된 일련의 연속적인 이벤트들을 말합니다. 각 스트림들은 서로를 고유하게 구분할 수 있는 이름 및 버전으로 구성된 식별자를 가집니다.

스트림 프로세싱이란?

스트림 프로세싱이란 연속적인 이벤트들에 작업을 수행하는 것을 의미합니다.

  • 이벤트를 소비해서 다른 이벤트 포맷으로 변환하는 무상태 서비스,
  • 낮은 지연시간과 높은 신뢰성을 보장하기 위해 메모리에 상태 데이터를 저장하고 처리하는 복잡한 서비스가 이에 해당합니다. (= 이전 이벤트들을 기억해 두고 의사결정에 이들을 활용)
    • ex. 주식가격이 5분동안 상승했는지 알고 싶다면 스트림 처리 시스템은 실시간으로 이전 이벤트들을 전부 기억하고 순서대로 처리합니다.

스트림 처리 분양에서 RealTime 이라는 단어는 실시간에 근접한 시간을 뜻한다고 볼 수 있습니다. 즉 시스템은 처리 결과를 수 밀리 초에서 수 초 이내에 제공하고 낮은 지연 시간을 유지하기 위해 최선의 노력을 다한다는 뜻입니다.

스트림 프로세싱 애플리케이션을 만들 때 애플리케이션의 무상태 또는 상태적인 특성이 설계에 아주 큰 영향을 미칩니다.

스트리밍 데이터 프로세싱 패턴

스트리밍 데이터 프로세싱 패턴은 실시간 이벤트들의 변환이나 필터링, 애그리게이션, 의미 있는 연속적인 이벤트 탐지 등을 통해 의미 있는 결과를 도출하는 데 중점을 두고 있습니다. 성능에서 고려해야할 중요한 점은 영구 데이터 스토어를 많이 사용하지 않아야 한다는 것입니다. 데이터 스토어에 접근하기 위해 소요하는 시간과 이때 발생하는 잠재적인 경합으로 인해 처리 지연 시간에 엄청난 영향이 발생할 수 있기 때문입니다.

1) 변환 패턴

변환 패턴을 사용해서 이벤트 소스의 이벤트를 변환해서 다른 포맷이나 구조, 프로토콜을 사용하는 다른 시스템에 발행할 수 있습니다. XML -> JSON 변환과 같은 일을 수행합니다. 이 패턴은 이벤트들이 가지고 있는 정보만 사용하는 경우가 대부분입니다.

메시지 변환

메시지는 전통적인 프로그래밍 언어를 사용한 코드로 변환할 수도 있고 데이터 매핑을 수행하는 전용 애플리케이션으로 변활할 수도 있습니다. 클라우드 환경에서 실행이 가능한 이같은 서비스 버스나 스트림 프로세싱 애플리케이션으로는 아파치 캐멀, KSQL, 아마존 키네시스, 애저 스트림 애널리틱스 등이 있습니다.

고려해야 할 사항들

이 패턴은 협력사 팀과 같이 서로 다른 팀과 함께 애플리케이션을 만들거나, 서드파티 애플리케이션을 사용해야 할 때와 같이 클라우드 네이티브 애플리케이션의 이벤트를 변환해야 할 경우 자주 사용합니다. 무상태 변환의 경우 클라우드 네이티드 애플리케이션을 아무 문제 없이 쉽게 확장 가능합니다. 서버리스 컴퓨팅을 사용할 수 있습니다.
반면 변환에 상태를 저장하고 관리해야하는 경우(ex. 최근 한 시간 동안의 평균 기온 계산을 위해 윈도우드 애그리게이션 패턴 구현)는 쉽게 수평으로 확장할 수 없습니다. 이런 애플리케이션은 순차 수송 패턴을 사용해 애플리 케이션을 나누고 확장할 수 있습니다.

2) 필터와 한계값 패턴

이벤트를 특정 조건 기준으로 걸러내거나, 또는 주어진 한계값 이내의 값을 가진 이벤트만 허용해야하는 경우 사용합니다.

어떻게 동작할까요

사용자가 들어오는 이벤트를 걸러낼 수 있는 조건을 제공합니다. 문자열 일부 일치, 정규 표현식, 비교연산자, 논리연산자 등과 함께 사용하여 필요한 이벤트만 받아볼 수 있습니다.

어떻게 사용할 수 있나요

이 패턴은 서비스 버스나 스트림 처리기와 같은 시스템에서 사용하기 좋습니다.

분류별로 이벤트 걸러내기

  • 온라인 상거래 플랫폼에서 배송 관련 정보 중 국내 배송과 국제 배송을 서로 구분해서 처리하고 싶은 경우.
  • 메시지 브로커가 제공하는 구독 필터를 사용해서 관련 데이터만 처리하도록 할 수 있음.
  • 그렇게 할 수 없는 경우, 마이크로 서비스나 서버리스 펑션 등을 중간에 사용해서 이벤트를 걸러내고 관련 이벤트만 발행하도록 만드는 것이 좋음. (verb == solve도 그런 경우)

경고를 위한 한계 값 적용

  • 은행 부정 탐지
  • 트랜잭션 중 아주 큰 금액인 경우에만 사람이 직접 부정 사용인지 여부를 검사하는 시나리오. 이벤트 걸러내는 조건으로 트랜잭션 일어나는 위치, 온오프라인 거래 등 포함하여 알리고, 사람이 정상 거래인지 검사함.

고려해야 할 사항들

이 패턴은 연관된 이벤트만 걸러내서 처리할 수 있게 할 뿐 아니라 관계 없거나 낮은 우선순위 이벤트를 버림으로써 부하를 줄일 수도 있습니다. 카프카와 같은 최신 메시지 브로커들은 대부분 기본적으로 이런 필터 기능을 제공합니다.

관련 패턴들

필터와 한계값 패턴은 다른 스트림 데이터 프로세싱 패턴과 함께 사용해서 이벤트들을 걸러내고 처리할 수 있습니다.

3) 윈도우드 애그리게이션 패턴(상태)

조건에 따른 이벤트 집합을 분석합니다. 애그리게이션 분석에는 총합이나 최솟값, 최댓값, 평균값, 표준 편차 개수 등이 있으며 윈도우는 애그리게이션에 사용할 이벤트 집합을 정의합니다. 윈도우는 시간 또는 이벤트 개수 등으로 지정할 수 있습니다. 윈도우는 슬라이딩 또는 배칭으로 동작하면서 윈도우에 이벤트들을 어떻게 더하고 제거할지 결정합니다. 이 패턴은 데이터를 그때그때 애그리게이션하면서 시간이 촉박한 비즈니스 결정 사항을 수 초 이내에 만들어야 할 때 유용하게 사용할 수 있습니다.

어떻게 동작할까요

애그리게이션
애그리게이션 작업은 윈도우 안에서 수행됩니다. 애그리게이션에 사용할 이벤트 수는 윈도우에 의해 제한되며 애그리게이션 결과는 다시 스트림 형태로 내보냅니다.

윈도우 동작
1분 단위로 움직이는 시간 기반 슬라이딩 윈도우를 사용해서 마지막 1분간 발생한 이벤트만 처리한다고 가정해보겠습니다. 윈도우는 윈도우에 이벤트가 추가되거나 제거될 때마다 윈도우 내의 모든 이벤트에 대한 애그리게이션 결과를 내보냅니다.

최적화하기 위해 이벤트가 도착할 때마다 윈도우에 추가하는 대신 슬라이딩 간격을 지정해서 윈도우가 얼마나 자주 움직일 것인지 정의할 수도 있습니다.(이벤트를 윈도우에 얼마나 자주 추가하고 제거할지를 결정) 이를테면 1분 단위로 움직이는 슬라이딩 윈도우에 1초 간격의 슬라이딩 인터벌을 지정해서 1초에 한 번씩 윈도우가 움직이도록 설정할 수 있습니다. 윈도우가 움직이면 이전 시간 동안 도착한 이벤트들을 윈도우에 모두 추가하고 시간이 지난 모든 이벤트를 제거합니다.

어떻게 사용할 수 있나요

윈도우드 애그리게이션 패턴은 상태를 저장합니다. (신뢰성이 중요하다면 신뢰성 있는 패턴과 함께 사용하는 것이 좋습니다.)

시간에 따른 이벤트 종합

  • 시간 간격별로 이벤트를 모아야 할 때 이 패턴 사용.
  • 트랜잭션의 부정 사용 탐지 경우, 최근 10분간 발생한 트랜잭션의 금액 합계를 구해서 상위 10명의 금액 사용자를 알아냄. 아주 큰 금액을 작게 나누어 작은 금액의 트랜잭션을 통해 송금하는 것을 탐지할 수 있음.
  • 10분 단위 윈도우를 1초 단위로 움직이도록 슬라이딩 간격을 지정하는 쿼리
    SELECT userNAme, SUM(transactionValue), as totalTransaction  
    FROM InputStream
    WINDOW time (10 min, 1 sec)
    GROUP BY UserName
    ORDER BY totalTransaction DESC
    LIMIT 10
    

길이별로 구간을 나누고 이벤트 종합

  • 이벤트 개수가 중요한 기준인 경우. ex) 서버 측에서 세 번 연속 요청 거부가 발생하면 경고를 받는 경우.
    SELECT serverId, SUM(isRequestRejected) as totalRejectedRequests  
    FROM InputStream
    WINDOW length (3)
    having totalRejectedRequests == 3  
    

위에서 질의에 의해 처리되는 모든 이벤트는 단일 서버에서 생성되었다고 가정하고 있습니다. 그렇지 않다면 나중에 살펴볼 순차 수송 패턴과 같은 다른 패턴을 사용해서 질의를 나누고 여러 서버에서 생성되는 이벤트를 처리하도록 만들어야 합니다.

고려해야 할 사항들

이 패턴의 가장 중요한 점은 상태를 가진다는 것입니다. 결과의 무결성과 신뢰성을 위해서는 신뢰할 수 있는 패턴을 사용해야합니다. 또한 높은 정확도와 효율성을 만족하는 모든 종류의 애그리게이션을 만드는 것은 불가능하다는 점 역시 유념해야합니다. 평균을 구하는 윈도우는 만들 수 있지만, 중앙값을 만드는 윈도우는 그럴 수 없습니다. 평균 값은 윈도우 내 이벤트의 합과 개수만 알면 되기 때문에 윈도우에 이벤트를 추가하거나 제거하면서 평균 값을 점진적으로 바꿀 수 있으나 중앙값의 경우 윈도우의 모든 이벤트를 전부 검사해야합니다. 이는 높은 지연시간을 유발하고 많은 저장공간을 요구합니다.

이러한 경우 애그리게이션을 처리하는 노드의 확장이 필요합니다. 높은 부하를 견딜 수 있고 수요에 따라 확장할 수 있는 시스템을 만들어야합니다. 확장성은 샤딩을 통해 이벤트를 나눔으로써 효과적으로 구현할 수 있습니다.
윈도우 없이도 애그리게이션을 처리할 수 있지만 윈도우 애그리게이션을 사용하는 이유는 공간 복잡도 제한 때문입니다. 윈도우 애그리게이션은 에스퍼, Siddhi 같은 스트림 처리 라이브러리 또는 클라우드 네이티브 스트림 처리 프로세스를 사용하는 것이 좋습니다.

관련 패턴들

  • 변환패턴: 애그리게이션 결과를 다른 포맷으로 변경
  • 신뢰성 패턴: 시스템 장애 복구
  • 순차 수송 패턴: 애그리게이션을 샤드 키 기반으로 나누고 병렬 처리
  • 서비스 오케스트레이션 패턴: 이벤트를 샤드 키 기반으로 나누어 처리
  • 스트림 조인 패턴: 다른 샤드에서 애그리게이션 결과들을 합침

4) 스트림 조인 패턴(상태)

서로 다른 스키마를 가지는 여러 스트림의 이벤트를 합칠 때 사용합니다.

어떻게 동작할까요

이 패턴은 합칠 이벤트를 식별할 수 있는 조건을 정의합니다. 이 조건은 합칠 각 이벤트 스트림의 속성 값을 사용해서 어떤 이벤트를 합칠지 알려줍니다. 간단한 비교 연산자를 사용해서 같은 ID 값을 가지는 모든 이벤트를 합칠 수도 있고, 또는 더 복잡한 조건을 사용할 수도 있습니다.
또한 다른 이벤트 스트림으로부터 관련 이벤트가 도착할 때까지 얼마나 많은 이벤트를 기다려야할지 결정하는 버퍼를 정의합니다. 버퍼 간격은 스트림별로 다르게 정할 수 있습니다.

어떻게 사용할 수 있나요

확산 및 조합

  • 같은 이벤트에 동시에 서로 다른 작업을 수행해서 그 결과를 조합함으로써 모든 이벤트를 단일 이벤트처럼 만들 수 있음.
  • 대출 애플리케이션이 어떤 이벤트를 받아 신용도 검사, 주소 검사, 신원정보 조회 등의 작업을 한다고 할 때 여러 작업을 병렬로 처리하고 마지막에 하나로 합쳐 은행에 전달하려고 함. 동일한 ID를 기준으로 조인하여 전달.
  • 작업에 오류가 있거나 네트워크 문제 등으로 이벤트를 보내지 않는 경우를 처리할 수 있는 방법도 마련해야함.
    • 버퍼 간격을 정의해서 유실된 이벤트를 찾은 다음 이에 해당하는 결과 버림.
    • 부분 결과만 가지고 의사 결정 데이터 생성.
    • 데이터 유실로 인한 승인 거절 또는 데이터 재 처리 요청

여러 종류의 이벤트 조인

  • 어떤 트윗이 올라오면 관련 주식의 가격을 알아내는 어플리케이션.
  • 윈도우를 사용해서 주가 스트림으로부터 최신 주식 가격을 전부 저장. 새로운 트윗에 ‘애플’이라는 단어가 포함된 경우 이 이벤트를 윈도우에 저장된 주가 이벤트와 합쳐서 처리..? 회사 이름과 같은 주가 이벤트를 찾은 다음 최신 주식 가격을 결과로 내놓음.
    • 주가 스트림은 매초
    • 트윗 스트림은 필터 적용?

고려해야 할 사항들

확산과 조합 같은 간단한 사용의 경우 메시지 브로커에서 이벤트를 바로 읽어와서 이벤트들을 성공적으로 조합할 때까지 응답을 미룰 수 있기 때문에 이벤트 유실이 발생하지 않습니다.
긴 시간 동안 여러 이벤트를 합치는 것은 어려운 일입니다. 기간이 길어질수록 요구하는 저장 공간의 크기가 커지고 처리 시간이 길어지기 때문입니다. 이 때는 순차 수송 패턴을 사용하여 이벤트들을 조합할 속성에 따라 샤드로 나누고 처리하는 것이 좋습니다. 조인 연산을 병렬로 처리할 수 있습니다.

관련 패턴들

  • 변환 패턴: 결과 이벤트를 만들기 위해 여러 이벤트 속성을 사용하고 변환
  • 신뢰성 패턴: 시스템 장애 등의 상황에 대응
  • 순차 수송 패턴: 관련 이벤트들을 샤드 단위로 나누어서 처리함으로 조인 연산을 확장

5) 임시적인 이벤트 정렬 패턴(상태)

스트림 프로세싱 분야에서만 사용하는 패턴입니다. 이벤트가 도착하는 순서를 토대로 패턴을 분석하고 이벤트가 발생했는지 여부를 탐지합니다.

어떻게 동작할까요

비결정적 유한 상태 기계처럼 동작합니다. 애플리케이션의 상태가 입력되는 이벤트와 현재 애플리케이션의 상태에 따라 바뀝니다. 각 상태에서 다른 상태로의 변화는 상태 그래프로표현할 수 있습니다. 이벤트가 특정 상태에 도달하면 사용자에게 이벤트 발생을 알립니다.

어떻게 사용할 수 있나요

이벤트 순차 발생 탐지

  • 신용카드 트랜잭션에서 사기 행위 탐지
  • 미국에서 트랜잭션이 발생 후 3시간 이내 미국 외 지역에서 트랜잭션 발생하는 경우를 탐지하려고 함.
  • 신용카드별로 새로운 상태 기계를 만들고 트랜잭션을 추적하여 이벤트 탐지함.
  • 시작 -> 미국에서 트랜잭션 발생 -> 미국 외에서 트랜잭션 발생 -> 부정 사용 탐지

이벤트가 발생하지 않음을 탐지

  • 차고문이 닫히지 않았음을 탐지
  • 시작 -> 차량이 빠져나갈 때까지 대기 -> 문이 닫힐 때까지 대기 -> 문이 열려있음(안 닫힘) 통지

고려해야 할 사항들

상태 기계들을 관리할 수 있도록 클라우드 네이티브 애플리케이션이 충분한 메모리 공간을 가지고 있어야 합니다. 순차 수송 패턴을 사용해서 이벤트를 여러 노드에 부산해서 확장하고 병렬로 처리할 수 있습니다.
이벤트가 생성된 순서로 전달되는 것이 중요합니다. 이벤트가 생성된 시간을 기록하고 이를 토대로 이벤트를 재배치 할 수 있도록 하면 이벤트 전송 과정에서 순서에 어긋난 경우를 바로잡을 수 있습니다.
애저 스트리밍 애널리틱스, 아파치 스파크, 아파치 플링크, 에스퍼, Siddhi 같은 스트림 프로세싱 시스템들이 이런 기능을 기본으로 제공합니다.

관련 패턴들

  • 변환 패턴: 일련의 이벤트들을 가지고 의미 있는 데이터를 만들 때
  • 신뢰성 패턴: 장애 복구
  • 순차 수송 패턴: 연관 이벤트들을 샤드로 배분하여 작업 병렬 처리
  • 버퍼를 이용한 이벤트 정렬 패턴: 이 패턴이 올바르게 동작할 수 있도록 이벤트 생성 시간을 기준으로 정렬

6) 머신 러너 패턴

머신러닝 모델을 미리 만들어 두어 변경 없이 새로운 이벤트에 기반한 예측, 온라인 머신러닝을 통해 예측과 학습을 동시에 할 수 있습니다.

어떻게 동작할까요

미리 정의된 머신러닝 모델: 미리 만들어진 모델은 PMML(Predictive Model Markup Language)와 같은 기술 사용해서 애플리케이션에서 불러와서 사용할 수 있습니다. 클라우드 네이티브 애플리케이션에서 API를 통해 호출하는 것도 가능합니다.

온라인 머신러닝 모델: 애플리케이션에 내장할 수도 있고 마이크로서비스로 만들 수도 있습니다.

어떻게 사용할 수 있나요

미리 정의한 머신러닝 모델로 결과 예측하기

  • 생산 라인에서 결함이 있는 부품 탐지.

온라인 머신러닝 모델

  • 과거에 축적된 데이터보다 앞으로 얻게될 데이터가 많은 경우
  • 공항 보안 검색에서 소요되는 시간을 예측해서 공항 내의 화면에 표시해주는 애플리케이션

고려해야 할 사항들

미리 정의된 모델은 주기적으로 업데이트 해주는 것이 좋습니다.

관련 패턴들

  • 변환 패턴: 모델이 예측한 데이터를 다른 데이터 포맷으로 바꿀 때 사용
  • 신뢰성 패턴: 온라인 머신러닝 알고리즘이 학습한 내용과 상태를 저장하고 복구

정리

다음 포스팅에서는 위에서 배운 스트림 프로세싱 패턴의 확장성 및 성능 최적화를 위한 패턴들을 알아보겠습니다.

Reference

클라우드 네이티브 애플리케이션 디자인 패턴 Chapter6. 스트림 프로세싱 패턴을 읽고 정리한 내용입니다.
자세한 내용은 책을 참고해주세요.