ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 카프카 핵심 가이드 1 - 카프카 입문
    책책책 책을 읽읍시다/프로그래밍 2023. 6. 6. 15:53

    저자 : 그웬 샤피라(Gwen Shapira), 토드 팔리노(Todd Palino), 라지니 시바람(Rajini Sivaram), 크레트 페티(Krit Petty)

    옮긴이 : 이동진

    카프카 핵심 가이드

    들어가며


    아파치 카프카 관련 다른 책들은 안 읽어봤는데, 이 책만으로도 카프카 기반 지식은 꽤 많이 얻어갈 수 있었다. Real MySQL처럼 각 기능에 대해 세세하고 적용점 예시까지는 안나와있지만, 기본 원리와 주의사항들은 잘 나와있는 편이다. 더 깊게 공부하려면 공식 문서와 코드레벨을 봐야할 것 같다. 초중반부가 카프카를 메세지 브로커로 사용하는 개발자에게 유용한 토픽, 파티션, API 등에 대해 나와있고, 후반부는 모니터링과 클러스터링 등 인프라적인 내용이 많이 서술되어 있다. 

     

    발췌 내용 정리


    1. 발행/구독 메세지 전달


     아파치 카프카의 특징에 대해 설명하기 전에, 발행/구독 메세지 전달(publish/subscribe messaging)의 개념과 데이터 주도 애플리케이션에서의 중요성을 이해할 필요가 있다. 발행/구독 메세지 전달 패턴의 특징은 전송자(발행하는 쪽)가 데이터(메세지)를 보낼 때 직접 수신자(구독하는 쪽)로 보내지 않는다는 것이다. 대신, 전송자(쓰는 쪽)는 어떤 형태로든 메세지를 분류해서 보내고, 수신자(읽는 쪽)는 이렇게 분류된 메세지를 구독한다. 발행/구독 시스템에는 대개 발행된 메세지를 전달받고 중계해주는 중간 지점 역할을 하는 브로커(broker)가 있다.

     

    초기의 발행/구독 시스템

     발행/구독 패턴을 따르는 많은 사례들은 비슷한 형태로 시작한다. 즉, 가운데 간단한 메세지 큐나 프로세스 간 통신 채널을 놓는 것이다. 예를 들어서, 어딘가로 모니터링 지표를 보내야 하는 애플리케이션을 개발했다고 치면, 그림 1-1과 같이 애플리케이션에서 지표를 대시보드 형태로 보여주는 앱으로 연결을 생성하고 그 연결을 통해 지표를 전송한다.

    발행자와 구독자가 직접 연결된 단일 지표 발행자

     모니터링을 시작하는 시점에서는 단순한 문제에 걸맞은 단순한 해법이라고 할 수 있겠다. 하지만 오래가지 않아서 좀 더 장기간에 걸쳐 지푯값을 분석하고자 한다면 이 대시보드가 그리 잘 작동하지 않는다는 걸 알게 된다. 지표를 받아서 저장하고, 분석하는 서비스를 새로 하나 만든다. 이 서비스가 작동하도록 하기 위해서는 애플리케이션을 고쳐서 두 시스템에 지푯값을 쓰게 만든다. 그리고 지표를 생성하는 애플리케이션이 세 개가 되면, 이 두 서비스에 똑같은 연결을 또 만든다. 동료가 서비스를 폴링해서 뭔가 문제가 있을 때 경보가 울리도록 하는게 좋다고 생각하면 각각의 애플리케이션에 대해 요청을 받아 지표를 응답하는 서버를 추가해야 한다. 시간이 좀 더 흐르면 이러한 서버들에서 지표를 가져다 여러 목적으로 활용하는 더 많은 애플리케이션들이 추가된다. 결과적으로 아래와 같은 아키텍처가 되는데, 이렇게 되면 연결을 추적하는 것은 더 힘들어진다.

    발행자와 구독자가 직접 연결된 여러 지표 발행자

     이러한 방식에서 발생하는 기술 부채(technical debt)는 명백하기 때문에 다소 개선의 필요가 있다. 모든 애플리케이션으로부터 지표를 받는 하나의 애플리케이션을 만들고, 이 지푯값들을 필요로 하는 어느 시스템이든 지표를 질의할 수 있도록 해주는 서버를 제공하면 된다. 이렇게 하면 아래와 같이 복잡성이 줄어든 아키텍처를 반들 수 있다. 이로써 간단한 메세지 발생/구독 시스템을 하나 만듬셈이다.

    지표 밠행 및 구독 시스템

    개별 메세지 큐 시스템

     지표를 다루는 것과 동시에 로그 메세지에 대해서도 비슷한 작업을 해줘야 한다. 또한, 프론트엔드 웹사이트에서의 사용자 활동을 추적해서 이 정보를 기계 학습 개발자에게 제공하거나 관리자용 보고서를 생성하는 데 사용해야 할 수도 있다. 이러한 경우에도 비슷한 시스템을 구성함으로써 정보의 발행자와 구독자를 분리할 수 있다. 아래 그림은 세 개의 발행/구독 시스템으로 이루어진 인프라스터럭처를 보여준다.

    다수의 발행/구독 시스템

     위 그림에 묘사된 포인트 투 포인트(point-to-point) 연결을 활용하는 방식보다 이쪽이 명백히 더 바람직하지만, 여기에는 중복이 많다. 이렇게 되면 버그도 한계도 제각각인 다수의 데이터 큐 시스템을 유지 관리해야 한다. 여기에 메세지 교환을 필요로 하는 사례가 추가로 생길 수도 있다. 비즈니스가 확장됨에 따라 확장되는, 일반화된 유형의 데이터를 발행하고 구독할 수 있는 중앙 집중화된 시스템이 필요하다.

     

    2. 카프카 입문


     아파치 카프카는 위에서 설명한 것과 같은 문제를 해결하기 위해 고안된 메세지 발행/구독 시스템이다. '분산 커밋 로그' 혹은 '분산 스트리밍 플랫폼'이라고 불리기도 한다. 파일시스템이나 데이터베이스 커밋 로그(commit log)는 모든 트랜잭션 기록을 지속성(durable)있게 보존함으로써 시스템의 상태를 일관성(consistency)있게 복구할 수 있도록 고안되었다. 이와 유사하게, 카프카에 저장된 데이터는 순서를 유지한채로 지속성 있게 보관되며 결정적(deterministic)으로 읽을 수 있다. 또한, 확장시 성능을 향상시키고 실패가 발생하더라도 데이터 사용에는 문제가 없도록 시스템 안에서 데이터를 분산시켜 저장할 수 있다.

    메세지와 배치

     카프카에서 데이터의 기본 단위는 메세지(message)이다. 메세지는 단순히 바이트의 배열일 뿐이기 때문에 여기에 포함된 데이터에는 특정한 형식이나 의미가 없다. 메세지는 키(key)라 불리는 메타데이터를 포함할 수도 있다. 키 역시 메세지와 마찬가지로 카프카 입장에서 특별한 의미가 없는 바이트 배열일 뿐이고, 메세지를 저장할 파티션을 결정하기 위해 사용된다. 같은 키값을 가진 메세지는 파티션 수가 변하지 않는 한 항상 같은 파티션에 저장된다.

     카프카는 효율성을 위해 메세지를 배치(batch) 단위로 저장한다. 토픽의 파티션에 쓰여지는 메세지의 집합이다. 메세지를 쓸 때마다 네트워크상에서 신호가 오가는 것은 막대한 오버헤드를 발생시키는데, 메세지를 배치 단위로 모아서 쓰면 이것을 줄일 수 있다. 물론 이것은 지연(latency)과 처리량(throughput) 사이에 트레이드 오프를 발생시킨다. 즉, 배치 크기가 커질수록 시간당 처리되는 메세지의 수는 늘어나지만, 각각의 메세지가 전달되는 데 걸리는 시간은 늘어나는 것이다.

    스키마

     카프카 입장에서 메세지는 단순한 바이트 배열일 뿐이지만, 내용을 이해하기 쉽도록 일정한 구조(혹은 스키마)를 부여하는 것이 권장된다. 각 애플리케이션의 필요에 따라 사용 가능한 메세지 스키마에는 여러 가지가 있는데, 가장 간단한 방법으로는 쓰기 쉽고 사람이 알아볼 수 있는 JSON이나 XML이 있다. 하지만 이 방식들은 타입 처리 기능이나 스키마 버전 간의 호환성 유지 기능이 떨어진다. 많은 아파치 카프카 개발자들은 아파치 에이브로(Avro)를 선호한다. 에이브로는 조밀한 직렬화 방식을 제공하는 데다 메세지 본체와 스키마를 분리하기 때문에 스키마가 변경되더라도 코드를 생성할 필요가 없다. 강력한 데이터 타이핑(typing)과 스키마 변경에 따른 상위 호환성, 하위 호환성 역시 지원한다.

    토픽과 파티션

     카프카에 저장되는 메세지는 토픽(topic) 단위로 분류된다. 토픽과 가장 비슷한 개념으로는 데이터베이스의 테이블이나 파일시스템의 폴더가 있을 것이다. 토픽은 다시 여러 개의 파티션(partition)으로 나누어진다. 대개 토픽에 여러 개의 파티션이 있는 만큼 토픽 안의 메세지 전체에 대해 순서는 보장되지 않으며, 단일 파티션 안에서만 순서가 보장될 뿐이다.

    프로듀셔와 컨슈머

     카프카 클라이언트는 이 시스템의 사용자이며, 기본적으로 프로듀서와 컨슈머의 두 종류가 있다. 좀 더 고급 클라이언트 API도 있는데, 데이터 통합에 사용되는 카프카 커넥트(Kafka Connect) API와 스트림 처리에 사용되는 카프카 스트림즈가 그것이다. 이 고급 클라이언트들은 프로듀서와 컨슈머를 기본적인 요소로 사용하며, 좀 더 고차원적인 기능을 제공한다.

     프로듀셔는 새로운 메세지를 생성한다. 다른 발행/구독 시스템에서는 발행자(publisher) 혹은 작성자(writer)라고도 부른다. 메세지는 특정한 토픽에 쓰여진다. 기본적으로 프로듀서는 메세지를 쓸 때 토픽에 속한 파티션들 사이에 고르게 나눠서 쓰도록 되어있다. 하지만 어떠한 경우에는 프로듀서가 특정한 파티션을 지정해서 메세지를 쓰기도 한다. 이것은 대개 메세지 키(key)와 키값의 해시를 특정 파티션으로 대응시켜 주는 파티셔너(partitioner)를 사용해서 구현된다. 이렇게 함으로써 동일한 키 값을 가진 모든 메세지는 같은 파티션에 저장되게 된다.

     컨슈머는 메세지를 읽는다. 다른 발행/구독 시스템에서는 구독자(subscriber) 혹은 독자(reader)라고도 한다. 컨슈머는 1개 이상의 토픽을 구독해서 여기에 저장된 메세지들을 각 파티션에 쓰여진 순서대로 읽어 온다. 컨슈머는 메세지의 오프셋(offset)을 기록함으로써 어느 메세지까지 읽었는지를 유지한다. 오프셋은 지속적으로 증가하는 정수값으로, 카프카가 메세지를 저장할 때 각각의 메세지에 부여해주는 또 다른 메타데이터이다. 주어진 파티션의 각 메세지는 고유한 오프셋을 가지며, 뒤에 오는 메세지가 앞의 메세지보다 더 큰 오프셋을 가진다(반드시 단조증가할 필요는 없다). 파티션별로 다음 번에 사용 가능한 오프셋 값을 저장함(대체로 카프카 자체에 저장됨)으로써 컨슈머는 읽기 작업을 정지했다가 다시 시작하더라도 마지막으로 읽었던 메세지의 바로 다음 메세지로부터 읽을 수 있다.

     컨슈머는 컨슈머 그룹(consumer group)의 일원으로서 작동한다. 컨슈머 그룹은 토픽에 저장된 데이터를 읽어오기 위해 협업하는 하나 이상의 컨슈머로 이루어진다. 컨슈머 그룹은 각 파티션이 하나의 컹슈머에 의해서만 읽히도록 한다.

    브로커와 클러스터

     하나의 카프카 서버를 브로커라고 부른다. 브로커는 프로듀서로부터 메세지를 전달받아 오프셋을 할당한 뒤 디스크 저장소에 쓴다. 브로커는 컨슈머의 파티션 읽기(fetch) 요청 역시 처리하고 발행된 메세지를 보내준다. 시스템 하드웨어의 성능에 따라 다르겠지만, 하나의 브로커는 초당 수천 개의 파티션과 수백만 개의 메세지를 쉽게 처리할 수 있다.

     카프카 브로커는 클러스터의 일부로서 작동하도록 설계되었다. 하나의 클러스터 안에 여러 개의 브로커가 포함될 수 있으며, 그중 하나의 브로커가 클러스터 컨트롤러의 역할을 하게 된다(컨트롤러는 클러스터 안의 현재 작동 중인 브로커 중 하나가 자동으로 선정된다). 컨트롤러는 파티션을 브로커에게 할당해주거나 장애가 발생한 브로커를 모니터링하는 등의 관리 기능을 담당한다.

     아파치 카프카의 핵심 기능 중에 일정 기간 동안 메세지를 지속성(durability) 있게 보관하는 보존(retiontion) 기능이 있다. 카프카 브로커는 토픽에 대해 기본적인 보존 설정이 되어 있는데, 특정 기간 동안 메세지를 보존하거나 파티션의 크기가 특정 사이즈에 도달할 때까지 데이터를 보존한다. 이러한 한도값에 도달하면 메세지는 만료되어 삭제된다. 각각의 토픽에는 메세지가 필요한 정도까지만 저장되도록 보존 설정을 잡아줄 수 있다. 예를 들어서, 사용자 활동 추적 토픽은 며칠 동안 유지할 수 있는 반면, 애플리케이션 지표는 겨우 몇 시간만 보전할 수 있는 것이다.

     

    댓글

Designed by Tistory.