책너두 (데이터 중심 애플리케이션 설계) 38일차 (~442p)

요약

  • 스트림 처리에 대한 내용을 이해함.
    • 이벤트 스트림 전송
      • 메시징 시스템
        • 생산자에서 소비자로 메시지를 직접 전달하기
        • 메시지 브로커
        • 메시지 브로커와 데이터베이스의 비교
        • 확인 응답과 재전송

메모

11장. 스트림 처리

  • 이번 장에서는 스트림 처리의 기본 개념을 소개하고 있음.
    • 스트림 처리는 시간이 지남에 따라 점진적으로 생성되는 데이터를 처리하는 방법으로, 일괄 처리와는 달리 데이터가 한정되지 않고 점진적으로 처리됨.
    • 일반적으로 스트림은 유닉스의 stdin과 stdout, 프로그래밍 언어의 느긋한 리스트, 자바의 FileInputStream과 같은 파일 시스템 API, TCP 연결, 인터넷 상의 오디오와 비디오 전송 등에서 사용됨.
  • 일괄 처리의 문제점은 입력의 변화가 처리 사이클이 끝날 때까지 반영되지 않는 것으로, 이 지연을 줄이기 위해 스트림 처리가 등장함.
    • 스트림 처리는 고정된 시간 조각이 없이 이벤트가 발생할 때마다 처리하는 방식임.
  • 이 장에서는 다음 주제들을 다룸.
    1. 스트림을 표현, 저장, 네트워크 상에서 전송하는 방법
    2. 스트림과 데이터베이스 사이의 관계
    3. 스트림을 연속적으로 처리하는 접근법, 도구, 그리고 애플리케이션 구축 방법
  • 스트림 처리는 데이터 관리 메커니즘으로 이벤트 스트림을 처리하며, 이를 통해 애플리케이션의 성능과 사용자 경험을 향상시킬 수 있음.
    • 이러한 스트림 처리는 실시간 검색 색인, 추천 시스템, 데이터 분석 등 다양한 분야에서 활용됨.
    • 이러한 스트림 처리를 통해 더 빠른 응답 시간과 실시간으로 반영되는 결과를 얻을 수 있어 사용자에게 보다 나은 서비스를 제공할 수 있음.

이벤트 스트림 전송

  • 이벤트 스트림 전송에서는 스트림 처리를 사용해 일괄 처리와 달리 레코드를 이벤트로 처리함.
    • 이벤트는 사용자 행동이나 장비에서 발생한 데이터로, 이벤트 발생 타임스탬프를 포함함.
    • 이벤트는 텍스트 문자열, JSON, 이진 형태 등으로 부호화되며, 부호화된 이벤트는 저장하거나 네트워크를 통해 전송할 수 있음.
  • 스트림 처리에서는 생산자(producer)가 이벤트를 생성하고, 여러 소비자(consumer)가 해당 이벤트를 처리할 수 있음.
    • 스트림 시스템에서는 관련 이벤트를 토픽(topic)이나 스트림으로 묶음.
  • 이론적으로 파일이나 데이터베이스가 생산자와 소비자를 연결하는데 충분하지만, 지연 시간이 낮고 지속적인 처리를 원할 때 데이터스토어를 이용한 폴링 방식은 비용이 큼.
    • 이 경우, 이벤트 알림 전달 목적으로 개발된 특별한 도구들이 더 적합함.
  • 스트림 처리를 사용하면 데이터를 더 빠르게 처리하고, 지연 시간을 줄이며, 실시간으로 반영되는 결과를 얻을 수 있음.
    • 이를 통해 더 나은 사용자 경험과 서비스를 제공할 수 있음.

메시징 시스템

  • 메시징 시스템은 생산자가 소비자에게 메시지를 전송하고, 이벤트를 알리는 등의 목적으로 사용됨.
    • 이를 위해 메시지 전송을 위한 기본적인 통신 채널인 유닉스 파이프나 TCP 연결을 활용하거나, 이를 확장한 발행/구독 모델을 사용함.
  • 메시지 전송 시 생산자와 소비자의 속도 차이로 인한 문제에 대해서는 메시지를 버리거나 큐에 버퍼링하거나 배압을 적용하는 방법이 있음.
    • 이때, 메시지를 큐에 버퍼링할 경우 큐 크기가 메모리 크기보다 더 커질 경우 시스템이 중단될 수 있으며, 디스크에 쓰는 경우 디스크 접근이 메시징 시스템의 성능에 영향을 줄 수 있음.
    • 또한, 노드가 죽거나 오프라인이 되었을 때 메시지의 손실을 막기 위해 지속성을 갖추는 방법을 사용할 수 있음.
      • 이때, 메시지의 유실을 허용할지 말지는 애플리케이션에 따라 달라지며, 메시지의 신뢰성은 매우 중요함.
  • 이와 비슷한 처리 보장을 위해 일괄 처리 시스템이 사용될 수 있음.
    • 이번 장 후반부에서는 스트림 문맥에서 이와 비슷한 처리 보장을 위해 어떻게 해야 하는지에 대해 다룸.

생산자에서 소비자로 메시지를 직접 전달하기

  • 직접 메시징 시스템은 중간 노드 없이 생산자와 소비자를 연결하여 메시지 전달이 가능함.
    • ex) UDP 멀티캐스트는 낮은 지연 시간이 필수인 주식 시장과 같은 금융 산업에서 사용됨.
      • 비록 UDP의 신뢰성은 낮지만, 애플리케이션 단의 프로토콜은 손실된 패킷을 복구할 수 있음.
  • ZeroMQnanomsg 같은 브로커가 필요 없는 메시징 라이브러리는 TCP나 IP 멀티캐스트 상에서 발행/구독 메시징을 구현함.
  • StatsDBrubeck는 네트워크 상의 모든 장비로부터 지표를 수집하고 모니터링하기 위해 UDP 메시징을 사용함.
  • 소비자가 네트워크에 서비스를 노출하면 생산자는 직접 HTTP RPC 요청을 보낼 수 있음.
    • 이 아이디어는 웹후크를 지원하는데, 서비스 콜백 URL을 다른 서비스에 등록하는 형식임.
  • 직접 메시징 시스템은 설계 상황에서 잘 동작하지만, 메시지 유실 가능성을 고려해 애플리케이션 코드를 작성해야 함.
    • 허용 가능한 결합은 제한적이며, 프로토콜이 네트워크 상에서 패킷 유실을 감지하고 재전송하더라도 직접 메시징 시스템은 일반적으로 생산자와 소비자가 항상 온라인 상태라고 가정함.
    • 소비자가 오프라인일 경우, 메시지 전달이 불가능하며 전송된 메시지는 손실될 수 있음.
    • 일부 프로토콜은 실패한 메시지 전송을 생산자가 재시도하게끔 하지만, 생산자 장비가 고장나면 재시도하려던 메시지 버퍼를 잃어버릴 수 있음.

메시지 브로커

  • 메시지 브로커(또는 메시지 큐)는 직접 메시징 시스템의 대안으로 사용되며, 메시지 스트림 처리에 최적화된 데이터베이스의 일종임.
    • 메시지 브로커는 서버로 구동되고, 생산자와 소비자는 서버의 클라이언트로 접속함.
    • 생산자는 브로커로 메시지를 전송하고, 소비자는 브로커에서 메시지를 읽어 전송받음.
  • 메시지 브로커를 사용하면 클라이언트의 상태 변경에 대처하기 쉬움.
    • 일부 메시지 브로커는 메모리에 메시지를 보관하고, 다른 브로커는 장애로 인해 메시지를 잃어버리지 않기 위해 디스크에 메시지를 기록함.
    • 소비 속도가 느린 소비자가 있는 경우, 브로커는 큐가 계속 늘어나게 함.(메시지를 버리거나 배압을 사용하는 것과는 반대로).
  • 비동기로 동작하는 소비자는 생산자가 메시지를 보낼 때, 브로커가 해당 메시지를 버퍼에 넣었는지만 확인하고 소비자가 메시지를 처리하기까지 기다리지 않음.
    • 메시지를 소비자로 배달하는 것은 정해지지 않은 미래 시점임.(대개 순식간이지만, 큐에 백로그가 있다면 상당히 늦을 수도 있음)

메시지 브로커와 데이터베이스의 비교

  • 어떤 메시지 브로커는 XA 또는 JTA를 이용해 2단계 커밋을 수행하기도 함.
  • 메시지 브로커와 데이터베이스에는 차이가 있지만, 일부 특징은 상당히 비슷함.
    • 데이터베이스는 삭제될 때까지 데이터를 보관하는 반면, 메시지 브로커 대부분은 소비자에게 데이터 배달이 성공하면 자동으로 메시지를 삭제함.
    • 메시지 브로커는 작업 집합이 작다고 가정함.
      • 큐 크기가 작고, 소비자가 느려서 메시지 브로커가 많은 메시지를 버퍼링해야 한다면, 처리 시간이 길어지고 처리량이 저하됨.
    • 데이터베이스는 보조 색인을 지원하고 다양한 검색 방법을 제공하는 반면, 메시지 브로커는 특정 패턴과 부합하는 토픽의 부분집합을 구독하는 방식을 지원함.
    • 데이터베이스에서의 질의 결과는 스냅을 기준으로 하지만, 메시지 브로커는 임의 질의를 지원하지 않고, 데이터가 변하면 클라이언트에게 알려줌.
  • 메시지 브로커는 전통적으로 JMS, AMQP와 같은 표준으로 캡슐화되어 RabbitMQ, ActiveMQ, Qpid, HornetQ, TIBCO Enterprise Message Service, IBM MQ, Azure Service Bus, Google Cloud Pub/Sub 등의 소프트웨어로 구현됨.

복수 소비자

  • 복수 소비자가 같은 토픽에서 메시지를 읽을 때 사용하는 주요 패턴에는 로드밸런싱과 팬아웃 두 가지가 있음.
    • 로드밸런싱 패턴은 각 메시지가 소비자 중 하나에게 전달되며, 브로커는 메시지를 전달할 소비자를 임의로 지정함.
    • 따라서 소비자들은 해당 토픽의 메시지를 처리하는 작업을 공유하게 된다. 로드밸런싱 패턴은 메시지를 처리하는 비용이 비싸서 처리를 병렬화하기 위해 소비자를 추가하고 싶을 때 유용함.
  • 팬아웃 패턴은 각 메시지가 모든 소비자에게 전달되며, 여러 독립적인 소비자가 브로드캐스팅된 동일한 메시지를 서로 간섭 없이 청취할 수 있음.
    • 팬아웃 방식을 사용하면 같은 입력 파일을 읽어 여러 다른 일괄 처리 작업에서 사용하는 것과 동일함.
  • 이 두 가지 패턴은 함께 사용 가능하며, 예를 들어 두 개의 소비자 그룹에서 하나의 토픽을 구독하고 각 그룹은 모든 메시지를 받지만 그룹 내에서는 각 메시지를 하나의 노드만 받게 할 수 있음.
  • AMQP에서는 같은 큐를 소비하는 클라이언트를 여러 개 둬서 로드 밸런싱을 구현할 수 있으며, JMS에서는 이 방식을 공유 구독(shared subscription)이라고 한다. 팬아웃 방식은 JMS에서는 토픽 구독, AMQP에서는 바인딩 교환으로 제공됨.

확인 응답과 재전송

  • 메시지 브로커는 메시지 소비자에게 메시지를 전달한 후, 소비자가 해당 메시지를 처리한 후에 브로커에게 명시적인 확인 응답을 보내야 함.
    • 만약 브로커가 확인 응답을 받기 전에 소비자와의 연결이 끊어지거나 타임아웃이 발생하면 브로커는 해당 메시지가 처리되지 않았다고 판단하고 다른 소비자에게 해당 메시지를 다시 전송함.
      • 이 때 메시지의 순서는 바뀔 수 있으며, 원자적 커밋 프로토콜을 이용하여 이러한 문제를 해결할 수 있음.
  • 메시지 브로커는 부하 균형 분산과 결합하면서 메시지 재전송을 사용하는 경우 메시지의 순서가 바뀔 수 있음.
    • 따라서 메시지 순서가 매우 중요한 경우에는 소비자마다 독립된 큐를 사용하여 부하 균형 분산 기능을 사용하지 않는 것이 좋음.

댓글

Designed by JB FACTORY