728x90
반응형

Kafka 정의

  • Distributed commit log
  • 데이터를 지속해서 저장하고 읽을 수 있으며 확장에 따른 성능 저하를 방지하여 데이터가 분산 처리될 수 있다.

 

메시지 발행과 구독

  • publish/subscribe 관계로 데이터 발행자가 발행/구독 시스템에 전송하면 구독자가 특정 부류의 메시지를 구독할 수 있도록 함
  • 메시지를 저장하고 중계하는 역할은 브로커가 수행
  • 메시지 발행 시스템에서즌 데이터 발행자가 직접 구독자에게 보내지 않는다!

 

초기의 발행/구독 시스템

  • 발행자와 구독자가 직접연결된 시스템에서 발전하여
  • 중간 브로커(서버)를 둔 아키텍쳐가 만들어졌다.
  • 모든 애플리케이션의 메트릭을 하나의 애플리케이션이 수신하고, 하나의 서버로 제공하여 해당 메트릭이 필요한 어떤 시스템에서도 쉽게 조회 가능

 

카프카 사용 이유

  • 중앙화된 전송 영역이 없어 end to end 연결이 복잡해진다
  • 데이터 파이프라인 관리가 어려워지고
  • 연결 시스템마다 다른 방식으로 구현 수 있다

 


메시지와 배치

  • 데이터의 기본단위: 메시지
  • 바이트 배열의 데이터로 특정 형식이나 의미를 갖지 않음
  • 카프카 메시지 데이터는 topic으로 분류된 partition에 수록되는데 이때 데이터를 수록할 파티션을 결정하기 위해 일관된 해시 값으로 키를 생성한다.
  • 카프카는 메시지가 생길때마다 보내는 게 아닌 효율성을 위해 모아 전송하는 형태의 배치로 파티션에 전송할 수 있다.
    • 배치의 크기가 증가하면 → 단위 시간당 처리되는 메시지 양이 증가하지만 메시지의 전송 시간도 증가함

 

스키마

  • 메시지의 구조를 나타내는 스키마를 사용
  • Json / XML 등을 사용
  • 스키마 버전 간의 호환성이 떨어져 아파치 Avro를 많이 사용(Apache에서 만듦)

 

토픽과 파티션

  • 카프카의 메시지는 토픽(topic)으로 분류하며 토픽은 DB의 테이블이나 파일 시스템의 폴더와 유사
  • 하나의 토픽은 여러개의 파티션(partition)으로 구성됨
  • 메시지는 파티션에 추가되는 형태로만 수록
  • 맨 앞부터 끝까지 순서대로 읽힌다
  • 메시지의 처리 순서는 토픽이 아닌 파티션 별로 유지 관리
  • 각 타피션은 서로 다른 서버에 분산되어 단일 서버로 처리할 때보다 훨씬 성능이 우수하다.

 

프로듀서와 컨슈머

  • 데이터를 쓰는 프로듀서(producer) - 데이터를 읽는 컨슈머(consumer)
  • 오프라인으로 대량의 데이터를 처리하도록 설계된 프레임워크인 하둡의 방법과 대비된다.
  • 프로듀서: 새로운 메시지를 생성하며 메시지는 특정 토픽으로 생성되고 기본적으로 메시지가 어떤 파티션에 수록되는지는 관여하지 않음
    • 프로듀서가 특정 파티션에 메시지를 직접 쓰는 경우가 있음 - 파티셔너 사용(키의 해시 값을 생성하고 그것을 특정 파티션에 대응시켜 지정된 키를 갖는 메시지가 항상 같은 파티션에 수록되게 함)
  • 컨슈머: 메시지를 읽는 주체
    • 하나 이상의 토픽을 구독하여 메시지가 생성된 순서대로 읽는다.
    • 메시지의 오프셋을 유지하여 메시지의 읽는 위치를 알 수 있다.
    • 오프셋은 지속적으로 증가하는 정수값이며 메시지가 생성될 때 카프카가 추가해준다.
    • 파티션에 수록된 각 메시지는 고유한 오프셋을 갖는다.
    • 주키퍼나 카프카에서는 각 파티션에서 마지막에 읽은 메시지의 오프셋을 저장하고 있으므로 컨슈머가 메시지 읽기를 중단했다 다시 시작해도 언제든 다음부터 읽을 수 있다.

  • 컨슈머는 컨슈머 그룹의 멤버로 동작
  • 한 토픽을 소비하기 위해 같은 그룹의 여러 컨슈머가 함께 동작
  • 한 토픽의 각 파티션은 하나의 컨슈머만 소비할 수 있다.
  • 한 컨슈머가 자신의 파티션 메시지를 읽는데 실패해도 같은 그룹의 다른 컨슈머가 파티션 소유권을 재조명받고 실패한 컨슈머의 파티션 메시지를 대신 읽을 수 있다.

 

브로커와 클러스터

  • 브로커: 하나의 카프카 서버
  • 프로듀서로부터 메시지를 수신하고 오프셋을 저장한 후 해당 메시지를 디스크에 저장
  • 클러스터의 일부로 동작하도록 설계되었다
  • 컨트롤러의 기능을 수행
  • 각 타피션은 클러스터의 한 브로커가 소유하며, 그 브로커를 파티션 리더라고 한다.
  • 일정 기간 메시지를 보존하는 기능도 있다
  • 각 파티션을 사용하는 모든 컨슈머와 프로듀서는 파티션 리더에 연결해야 한다.
  • 다중 클러스터
    • 데이터 타입에 따라 구분 및 처리
    • 요구사항에 따라 분리 처리
    • 다중 데이터 센터 처리
    • 다중 클러스터를 지원하기 위해 미러 메이커를 사용한다.

 

카프카를 사용하는 이유

  • 다중 프로듀서, 컨슈머
    • 다중 프로듀서, 컨슈머가 상호 간섭 없이 어떤 메시지 스트림도 읽을 수 있다.
  • 디스크 기반 보존
    • 메시지를 보존할 수 있어 컨슈머를 항상 실시간 실행시키지 않아도 된다.
    • 처리가 느리거나 접속이 폴주해서 메시지 읽는데 실패해도 데이터가 유실될 위험이 적다
  • 확장성
    • 브로커 1대부터 시작하여 규모에 따라 브로커를 수백대로 증가시키기고 대규모 클러스터로 묶어 사용할 수 있다.
    • 동시에 여러 브로커에 장애가 생겨도 복제 팩터를 더 큰 값으로 했다면 대응할 수 있다.

이용 사례

  • 활동 추적
  • 메시지 전송(메일, 푸시 알림)
  • 메트릭 로깅
  • 커밋 로그
  • 스트림 프로세싱
728x90
반응형
728x90
반응형
더보기

'일상 속 사물이 알려주는 웹 API 디자인' 읽은 내용 정리

첫 글 쓰기 전에...

API 개발이야 여러 번 해 봤지만 제대로 설계를 하고 개발한 적은 거의 없다고 본다.

그저 개발하기 급하게 개발한 못난이 API 투성이.. ㅠㅠ 

그러다가 한 반년 전에 개발한 API를 봤는데 너무나도 엉망이라 ㅋㅋㅋㅋㅋ 진짜 너무나도 거지 같아서 새로 설계하고 다시 짜렸는데 반년 전의 나와 지금의 나의 다른 점은.. 크게 없으므로 제대로 공부를 좀 해보고 개발하려고 공부하려고 한다!

책은 그냥 이 전에 개발 잘하시는 책임님이 사시던거 기억해두고 따라 샀던 책이라 어디 구석탱이에 있던 게 생각나 꺼내왔다.

고럼 화이팅 하매~~~

 


1부. API 디자인의 기초

1장. API 디자인이란 무엇인가

 

API는 인터페이스로 시스템 간 통신을 위한 인터페이스로 작용한다.

스마트폰의 예시를 들어봤을때,

스마트폰 UI와 비교를 들었는데, 스마트폰 화면을 터치하여 모바일 애플리케이션과 사람 간의 상호작용하는 역할을 하는 UI가 애플리케이션이 다른 애플리케이션과 상호작용을 하기 위해 작용하는 프로그래밍 인터페이스인 API와 비교할 수 있다.

모바일 애플리케이션이 백엔드와 커뮤니케이션하기 위해 인터넷을 사용하는데 HTTP를 사용 -> 그래서 웹 API라는 것

 

예를 들어 소셜 네트워크에 사진과 글을 올리는 과정을 설명하는데,

소셜 네트워크 백엔드가 사진과 텍스트를 수신하면, 사진은 서버의 파일 시스템에 저장되고, 텍스트는 사진의 식별자와 함께 데이터베이스에 저장된다. 

하진을 저장하기 전에 직접 만들어 둔 얼굴 인식 알고리즘을 이용해 사진 속에 친구가 포함되어 있는지 확인할 수도 있다.

 

위 과정을 확장하면 애플리케이션 하나가 여러 독립된 애플리케이션을 다루는 상황도 상상해 볼 수 있다고 한다.

API를 통해 사진과 텍스트를 저장하고, sns 백엔드에서는 얼굴인식 API, 저장 API, 타임라인에 추가 API 등을 호출하여 작업이 이루어진다고 이해했다. 이런 과정이 레고와 같다고 한다.

API로 접근이 가능해 어디서든 실행 가능하니 동시에 여러 곳에서 사용 가능하며 이러한 점이 API의 성능과 확장성을 관리하는데 유리하다.  

 

API 디자인이 중요한 이유

API를 사용하는 consumer 입장에서 사용하기 쉬워야 하기 때문인 것이 내가 생각하는 첫 번째 이유인 듯하다.

외부 API를 사용하는 경우라면 누가 개발한 지 모른 채 사용하게 되는데 이때 사용에 어려움이 없어야 좋은 API라고 할 수 있기 때문이다. 

이러한 API를 사용하는 개발자의 경험을 Developer Experience라고 한다. 사용하기 유용하고 쉽도록 개발하는 것이 API 개발의 키라고 한다.

 

API는 구현을 숨긴다

API 내부가 어떻게 구현되는지 consumer는 알 필요가 없다.

음식점에서 음식을 주문하는 경우와 비교를 했는데, 우리가 음식점에 가서 음식을 주문할 때 요리가 어떻게 되는지는 알지 못하고 점원을 통해 음식 주문과 서빙을 받는다.

이 점이 API를 통해 상호작용하는 점과 비슷하다. API에게 요청한 결과가 구현되고 수행되는 것은 provider 애플리케이션에서 일어난다.

 

어설픈 API 디자인은 끔찍한 결과를 초래

형편없이 디자인된 제품들은 잘못 쓰이거나 제대로 쓰이지 않거나 아예 쓰이지 않는다. 사용자들에게만 위험한 것이 아니라 제품을 만든 조직에도 위험하다.

(내가 만든 API가 이런 상황.. ㅠㅠㅠ)

상황이 어찌 됐든 간에 API 디자인 결함은 이 API를 사용하는 소프트웨어가 들이는 시간과 노력과 비용을 증가시킨다,

그러므로 API를 적절하게 디자인하는 법을 학습하면 된다.


모든 API가 이해하기 쉽고 사용하기 쉽게 만들어져야 한다.

라는 것이 결론이며 내가 개발해왔던 API를 생각해보면 그때는 reasonable 하다고 생각했던 것들이 전혀 그렇지 않고 내가 놓치고 개발한 점들도 참 많다. 이제라도 다시 개발해 볼 생각을 한 것만으로도 기특하다고 해야 할까.. ㅎㅎ

728x90
반응형
728x90
반응형

Kafka consumer group 모니터링 중 "Preparing rebalance" 상태가 떠서 정확히 알아볼 겸 consumer state 에 대한 정리...

(기초는 차차 정리하고 일단 당장 궁금한 것부터!)

Rebalancing 정의

  • 카프카 컨슈머 그룹을 구성하여 데이터를 처리할 때 운영상황에서 마주치는 다양한 경우의 수에 대해
  • 그룹에 참여하는 컨슈머 클라이언트 구성에 변화가 생길 경우 이 변화를 반영하기 위한 과정
  • 컨슈머 클라이언트를 사용하여 필요한 논리적인 그룹을 형성하고, 그 그룹 멤버들끼리 리소스(파티션)을 적절히 분배하는 프로세스

 

Consumer Group

  • 특정 토픽에 발행된 메시지를 consumer group이라는 논리적 멤버십을 제공함으로서 각 그룹에서 목적에 맞게 읽고 처리할 수 있도록 함
  • consumer group과 그 멤버 인스턴스, 토픽의 파티션과의 관계는 복잡함
  • 컨슈머 인스턴스 제약
    • 카프카에서 1개 파티션은 consumer group 내의 최대 1개 인스턴스까지만 접근 가능
    • 즉, 1개 consumer group 인스턴스 수가 토픽이 가진 파티션 갯수보다 많을 수 없음
    • 다시 적자면, 파티션 수가 consumer group내에서 실제 컨슈밍을 진행하고 있는, 최대 active consumer 갯수를 제한함
    • (consumer group과 파티션 사이의 관계가 있다는 것이며 이런 맥락에 기반하여 분산 처리 및 로드 밸런싱이 이루어짐)

 

Kafka Rebalance Protocol

  • 토픽을 컨슈밍할 논리적인 그룹을 형성하고 파티션을 재분배하는 과정
  • Group management를 사용하여 카프카 클라이언트들을 논리적인 그룹에 참여시킴으로서 cooperating 하며
  • Cooperating 과정에서 그룹 코디네이터(Group Coordinator)는 GroupCoordinator 인스턴스를 백그라운드 프로세스로 실행하며 consumer group을 관리하는 역할을 가진 카프카 브로커임
  • Kafka Rebalancing Protocol에서 코디네이터의 역할 대신 클라이언트 단의 역할이 크게 작용하게 되며, 이에 따른 장점이 있음
    • 클라이언트 자체로 로드밸런싱 알고리즘을 수행: autonomy → 클라이언트가 로드벨런싱 자체의 디테일 작업에 집중하며 브로커의 코드가 단순화됨
728x90
반응형
728x90
반응형

카프카 토픽 파티션 갯수 설정

토픽을 새로 생성했는데 파티션을 몇개로 설정할지 고민에 빠졌다.
파티션 갯수를 늘리면 로드가 줄어들기는 하지만 늘리는 만큼 복제 지연 이슈가 있을 수 있으니 적당히 나눠야 한다.

바람직한 갯수는 아래와 같다.
#partitions = desired throughput / partition speed

예를 들어 하루에 1TB 의 throughput을 원한다고 하고 하나의 파티션 속도가 10MB/s 라면
1TB/24h = 11.5MB/s 이므로
대략 1개~2개 정도면 원하는 throughput을 만족할 수 있는 속도가 나온다.

728x90
반응형
728x90
반응형


Scala best practices에 따르면 sequence(list, map 등) 으로부터 head를 뽑을 때 `head` 보다는 `headOption` 사용을 권장

Seq.empty[Int].head
-> head of empty list exception 발생

headOption은 sequence의 head를 뽑아내는 좀 더 안전한 방법!
Seq(1, 2, 3).headOption
// res0: Option[Int] = Some(1)

Seq.empty[Int].headOption
// res1: Option[Int] = None

exception 방지를 위해서는 None이 아닌 조건을 넣으면 될듯

728x90
반응형
728x90
반응형

개발 테스트를 하다가 

카프카로부터 메시지를 컨슈밍하는 애플리케이션을 종료했는데도 계속 컨슈밍하는 현상이 발생했다.

제대로 종료되지 않아 유령처럼 떠돌아 다녔던 것..

(intellij에서 실행하는 프로그램 또는 자바 기반 프로세스는 프로세스명이 "java.exe"d이다)

 

그 외에 메모리를 많이 잡아먹는 백그라운드 프로세스를 확인하거나 종료하기 위해 실행중인 프로그램을 확인하는 명령어를 공유해보려고 한다.

 

tasklist

현재 실행중인 백그라운드 프로세스 확인

 

taskkill

현재 실행중인 백그라운드 프로세스 중지

- 프로세스 파일명으로 중지

    > taskkill /f /im [프로세스명]

 

cmd 를 실행하여 위 명령어를 통해 확인하고 중지할 수 있다.

728x90
반응형

+ Recent posts