Event Hubs, Kafka로 사용시 offset reset 현상

눕눕·2023년 11월 29일
0

Kubernetes 도입하기

목록 보기
6/8

어떤 현상이야?

  • 처리한 메시지가 재처리 된다.
  • 좀 더 자세히 설명해 보자면, 처리하고 나서 한참 뒤에 갑자기 동일한 시간에 메시지가 다시 처리된다.

어떻게 쓰고 있는데?

위와 같은 현상을 겪은 사람은 나와 비슷한 환경이거나, 골자는 비슷할 것이라 본다.

아래는 현재 내가 사용하고 있는 환경이다.

  • kubernetes 위의 pod로 consumer가 띄우고 쓰고있다.
  • consumer들은 keda로 hpa를 컨트롤 한다.
  • keda는 event hub scaler가 아닌 kafka로 사용한다.
  • topic 중 특정 topic들은 메시지가 간헐적으로 들어온다.

좀 더 깊게 가보자구!!

발단

위 그래프의 왼쪽과 오른쪽 메시지들이 보이는가?
처리되고 1주일 뒤에 다시 해당 메시지들이 재처리되면서 오류를 뿜어대서 같은 메시지가 계속 쌓이는 부분이다. 여기서 같은메시지가 계속 쌓인다는 포인트가 아닌, 1주일뒤에 처리되었던 메시지가 다시 재처리 된부분에 집중을 해야한다.

원인 분석

재처리가 되는 이유는 여러가지가 있을 수 있지만, 나는 위 이슈를 다룰 때 신기하게 봤던 부분이 2군데가 있었다.

1. 1주일 전과 동일한 시간

아래와 같이 정확히 시간과 분까지 포함해서, 1주일 뒤에 재처리가 진행되었다.
11/14 18:24 (위)
11/21 18:25 (아래)

2. 1주일 뒤에 재처리 될 때, incoming 없이 outgoing부터 트래픽이 있다.

1번의 아래 그림을 보면 되는데, outgoing이 먼저 찍혀있는 부분을 볼 수 있다. 이 topic을 물고 있는 consumer가 처리하지 못한 메시지를 순환해서 받는 구조가 아니었다면 outgoing만 볼 수 있을 것이다.

그리고 Apache Kafka의 offset 정보도 retention 제한이 있다. 1.x 버전은 1일이고 2.x 버전은 1주일 이다. 1일 또는 7일 동안 새로운 offset으로 갱신되지 않으면 offset 정보는 사라진다. offset 정보가 없다면 consumer에서 열 때, auto.offset.reset 설정값에 따라 읽는 위치가 달라진다.

추리

위의 2가지 부분을 미루어 봤을때, 매우 높은 확률로 offset 정보가 reset되어 재처리 된것 같았다. 이 부분을 조금 더 확실히 보기 위해, ms 티켓 열어서 엔지니어분과 함께 로그를 보았지만 offset reset 된 로그를 확인하기는 힘들었다. Event Hubs 쓸 때, kafka 방식으로 쓰면 세들어 사는 느낌이랄까요?

이해가 안가는 부분은 아니다. Event Hubs를 쓸때 기존 kafka 쓰던 사람들 편하게 쓰라고 편의를 봐준 부분이니...

나는 메시지 retention을 168시간으로 사용하고 있었으며, offset.retention.minuate(broker에 있는 설정 값으로, offset reset 시간을 설정하는 값이다.) 설정 값이 2.x 버전에서는 defatul 7일(168시간)이니, 운이 없으면 offset이 삭제된다고 보면된다. 특히나 메시지는 바로 1초단위로 체크하면서 삭제되는게 아닐테니 더욱 가능성이 높다고 보여진다.

offset reset 관련해서 구글링해보면, 대부분 consumer가 없는 환경에서 새로운 commit 정보가 없을때 이러한 현상이 일어난다고 서술되어져 있다.

그럼 내 서비스는 왜 이렇게 되어버렸나?
이 질문에는 keda가 한 몫했다고 볼 수 있다. topic에 commit 되지 않은 메시지가 없으니 hpa를 통해 replica를 0으로 만들어 버렸고, error topic 특성상 오류나는 경우가 많이 없기에, 7일간 해당 hpa가 0에서 1로 변경되는 일이 없었다. 그래서 offset 정보가 삭제 되었고, keda metric 서비스도 정신 못차리고 earliest로 읽어서 부랴부랴 hpa를 올렸고, consumer 또한 earliest로 읽어서 재처리한 것으로 보여진다.

위에서 언급한 consumer에서 earliest로 읽는 부분은, consumer에서 kafka와 연결할 때, auto.offset.reset이라는 값을 통해, offset 정보가 없을 때, 어디에 offset을 두고 작업을 시작할까? 라는 부분을 설정할 수 있다.

내 서비스는 이부분에서 earliest로 되어져 있었다.그리고 아주 뜨거운 화요일이 되었다.

방지 방법은?

일반적인 kafka를 쓰시는 분들이라면 간단하게 broker쪽 설정인 offset.retention.minuate 값을 늘리면 되지만, Event Hubs에서는 offset.retention.minuate를 설정할 수 없었다. 따라서 아래 3가지 중 하나를 택하면 된다.

  1. consumer에서 auto.offset.reset 값을 latest로 설정
  2. consumer를 상시로 띄워놓기 (이 방법이 되는것으로 몇몇 글을 봐서 해봤는데 안됐다 결국)
  3. 재처리 해도 상관없을 로직을 가져가는 방법

나는 이중에 2번을 선택했다.3번은 상황에 따라서 유니콘 같은거다. 테스트 할 부분만 늘어나고 시간적 비용만 소모될 확률이 있다. (2번 안되서 해당 topic에 주기적으로 commit용도로 msg를 넣는 방법을 택했다.)

마치며

지난주 뜨거운 화요일을 만들어 주었던 범인을 검거 완료!!

profile
n년차 눕눕

0개의 댓글