백그라운드 작업은 규모를 고려한 웹 애플리케이션을 고려할 때 핵심 요소 중 하나입니다. 기본 아이디어는 간단합니다. 클라이언트가 웹 애플리케이션에 요청을 하고 해당 요청을 처리하면서 앱은 시간이 많이 걸리는 여러 작업을 수행합니다. 클라이언트에 더 빠르게 응답할 수 있도록 앱은 백그라운드 처리 시스템에 백그라운드 작업을 추가합니다. 그런 다음 계산이나 I/O 작업과 같은 모든 무거운 작업을 백그라운드 처리에 맡깁니다. 백그라운드 작업을 효과적으로 활용하는 것은 웹 애플리케이션을 확장할 때 가장 중요한 구성 요소 중 하나입니다.
Rails 개발자로서 우리는 선택할 수 있는 몇 가지 환상적인 라이브러리를 가지고 있으며, 모두 서로 다른 장점과 단점은 물론 백엔드 데이터베이스까지 갖추고 있습니다. 이러한 라이브러리를 사용하면 무거운 작업을 쉽게 수행할 수 있으므로 애플리케이션이 더 빠르게 응답하고 더 적은 리소스로 더 많은 사용자에게 서비스를 제공할 수 있습니다.
최근까지 우리는 Sidekiq을 사용하여 Honeybadger의 백그라운드 처리 작업 대부분을 수행했습니다. 이는 우리가 수집하는 막대한 양의 데이터를 처리하기 위해 눈부시게 빠른 사용자 경험과 강력한 파이프라인을 유지하는 데 중요한 역할을 했습니다.
사이드킥이 우리에게 부족한 점은 무엇인가요?
안정성에도 불구하고 Redis에는 몇 가지 제한 사항이 있습니다. 최근까지 우리는 오류 추적 엔드포인트에 대한 수집 처리를 포함하여 모든 작업 처리에 Sidekiq을 사용했습니다. 오류 트래픽은 매우 가변적입니다. 대기열에 있는 작업 수가 10배 또는 20배 증가하는 경우가 많았으며, 그 결과 자동 크기 조정으로 따라잡을 수 있을 만큼 충분한 작업자가 확보될 때까지 큰 백로그가 발생했습니다. 하지만 더 큰 문제는 ElastiCache 클러스터의 메모리 고갈이었습니다.
ElastiCache 클러스터를 통과하는 작업 트래픽이 충분하여 다운스트림 처리가 크게 지연되면 클러스터의 메모리가 부족해질 위험이 있습니다. 대기열이 아닌 데이터를 저장하기 위해 별도의 클러스터를 사용하지만 시간이 지남에 따라 일부 대기열이 아닌 데이터가 기본 클러스터에도 표시되어 메모리 부족 오류가 발생할 경우 제거될 수 있습니다. 하지만 더 중요한 문제는 클러스터에 메모리가 부족할 때 새 작업을 수락할 수 없다는 점이었습니다.
두 번째 문제는 Redis/ElastiCache가 volatile-lru를 사용한다는 것입니다. 기본적으로 퇴거 정책. 결과적으로 메모리 사용량이 높을 때 Redis는 TTL 세트를 사용하여 가장 최근에 사용된 데이터를 제거합니다. 어느 시점에서 Honeybadger는 Redis가 의도하지 않았을 때 캐시를 지우기 시작할 정도로 메모리 사용량이 높은 이벤트를 발생시켰습니다. 다행히 제거된 데이터는 재현 가능하므로(따라서 TTL) 영구 데이터는 손실되지 않았습니다.
그럼에도 불구하고 해결해야 할 한 가지 질문이 남았습니다. 유사한 이벤트가 발생하여 재구축할 수 없는 데이터가 손실되기 시작하면 어떻게 될까요? 고객 데이터가 절대 손실되지 않도록 하려면 어떻게 해야 합니까? 고객 오류 데이터를 처리하는 것이 우리 비즈니스의 핵심이므로 데이터 손실에 탄력적인 시스템이 필요합니다.
Kafka를 사용하여 데이터 수집
Kafka는 확장성과 탄력성을 모두 제공하는 분산 이벤트 파이프라인입니다. 최근 Insights 출시를 통해 Kafka를 이벤트 데이터 처리를 위한 인프라로 구축하는 데 많은 경험을 얻었습니다. 그 후에는 동일한 기술 스택을 사용하여 오류 수집 데이터를 처리하기를 원했습니다. 우리는 Kafka를 사용하여 더 나은 확장성과 더 저렴한 비용으로 중복 스토리지를 달성하는 것을 목표로 했습니다.
Insights를 위해 자체 AWS MSK 클러스터를 실행하고 있었기 때문에 이미 인프라와 자동 확장 설정이 있었습니다. 이는 우리가 "단지" 몇 가지 주제를 설정하고 Sidekiq 작업자와 동일한 코드를 실행하는 몇 가지 소비자를 생성해야 함을 의미했습니다. 개념은 매우 간단하여 Kafka 소비자를 미세 조정하는 데 더 집중할 수 있었습니다.
Sidekiq에서 Karafka로 마이그레이션
Honeybadger는 장엄한 단일체로 설계되었으며 Karafka는 동일한 아키텍처를 유지하도록 도와줍니다. 우리는 이미 Karafka를 사용하여 일부 Insights 데이터를 처리해 왔기 때문에 몇 명의 새로운 소비자를 추가하는 것은 간단한 작업이었습니다.
Karafka와 Sidekiq의 주요 차이점 중 하나는 작업을 검색하는 방법입니다. Karafka를 사용하면 단일 소비자 실행으로 작업이 일괄 처리되고 함께 처리됩니다. 소비자에서는 메시지 배열을 반복하고 Sidekiq 작업자를 인라인으로 실행할 수 있습니다.
class NoticeConsumer < ApplicationConsumer
def consume
messages.each do |message|
NoticeWorker.new.perform(message.payload)
end
end
end
우리가 고려해야 할 또 다른 차이점은 오류 처리가 작동하는 방식입니다. Sidekiq을 사용하면 각 작업이 원자적이므로 작업자는 재시도 및 실패 콜백을 통해 자체 오류를 처리합니다. Kafka의 일괄 처리 동작을 사용하면 오류 처리를 위한 더 많은 옵션이 있습니다. 특히 Karafka는 Dead Letter Queue라는 메커니즘을 제공합니다. 이를 통해 일괄적으로 또는 개별적으로 오류 처리를 지정할 수 있습니다.
dead_letter_queue(
topic: "ingestion.errors.dead",
max_retries: 5,
independent: true
)
Karafka 소비자는 개별 메시지 처리에 실패할 때마다 5번 재처리를 시도합니다. 5번째 시도에서 실패하면 지정된 주제로 메시지가 전송됩니다. independent: true 옵션은 전체 배치가 아닌 실패한 메시지만 DLQ로 보내야 함을 소비자에게 알려줍니다.
Karafka 모니터링 및 확장
알고 보니 Karafka 소비자를 모니터링하고 확장하는 것은 꽤 복잡합니다. AWS/MSK와 Karafka 모두에서 추적할 수 있는 항목이 많으며 시스템을 조정하기 위해 돌릴 수 있는 손잡이도 많습니다. 코드가 수행하는 작업, 데이터 흐름의 동작에 세심한 주의가 필요합니다.
AWS CloudWatch를 사용하여 많은 것을 모니터링하지만 다음은 우리가 살펴보는 몇 가지 Kafka 관련 지표입니다.
- SumOffsetLag — 지정된 주제 및 소비자 그룹에 대해 이는 모든 파티션의 모든 오프셋 지연의 합계입니다.
- 예상 최대 시간 지연 — 특정 주제 및 소비자 그룹에 대한 예상입니다. 현재 오프셋까지 모든 파티션을 따라잡는 데 걸리는 시간.
Karafka는 또한 몇 가지 훌륭한 도구를 제공하지만 이 데이터를 게시하고 직접 저장해야 합니다.
- 처리_지연 * — 이 값은 소비된 모든 메시지 배치에 사용할 수 있습니다. Karafka가 Kafka로부터 메시지를 받아 처리를 시작하는 데 걸린 시간을 알려줍니다.
- 소비_지연 * — 이 값은 processing_lag와 유사합니다. 단, 일괄 처리의 마지막 메시지가 Kafka 시스템에 입력된 시점부터 소비자가 처리를 시작할 때까지의 시간입니다.
- 기간 * — 소비자가 전체 메시지 배치를 처리하는 데 걸리는 시간입니다.
결과적으로 Sidekiq 프로세스 확장은 Karafka 소비자 프로세스 확장과 매우 다릅니다. Sidekiq의 병렬화를 늘리면 Redis 인스턴스가 처리할 수 있는 모든 프로세스에 더 많은 프로세스를 추가할 수 있습니다. Kafka를 사용하면 주제에 파티션당 최대 1개의 프로세스가 있어야 합니다. 일반적으로 Kafka 소비자는 2개 이상의 파티션에 할당될 수 있으므로 계획한 것보다 더 많은 파티션을 갖고 싶을 것입니다.
기억해야 할 또 다른 사항은 Kafka 소비자를 확장 및 축소하는 작업이 매우 오래 걸릴 수 있다는 것입니다. 소비자 그룹에서 소비자를 추가 및 제거하려면 그룹의 균형을 다시 조정해야 합니다. 이는 필요에 따라 파티션을 다시 할당하는 것을 의미합니다. 재할당 중에 소비자는 메시지 처리를 중지합니다. sticky-cooperative를 사용하면 이 문제를 어느 정도 완화할 수 있지만 일반적으로 리소스를 과도하게 프로비저닝하여 재조정을 피하는 것이 좋습니다.
현재 SumOffsetLag을 모니터링 중입니다. 확장 측정항목 중 하나로 사용됩니다. 주목해야 할 중요한 점은 재조정 중에는 이 측정항목이 보고되지 않는다는 것입니다. 상상할 수 있듯이 재조정 기간 동안 이 측정항목은 재조정이 완료될 때까지 급격히 증가합니다. 이것이 바로 규모를 최소한으로 유지하는 것이 중요한 또 다른 이유입니다.
Honeybadger에서 Karafka의 다음 단계는 무엇인가요?
우리는 Kafka/Karafka 구현을 한 달 넘게 100%로 실행해 왔으며 꽤 만족스럽다고 해도 과언이 아닙니다. 그럼에도 불구하고 필요할 경우 버튼을 눌러 언제든지 Sidekiq으로 돌아갈 수 있다는 점을 아는 것은 좋은 일입니다. 이는 이러한 시스템에 유지 관리 작업이 필요할 때 훨씬 더 큰 탄력성을 제공합니다.
Sidekiq에서 Karafka로 마이그레이션하는 과정에서 우리는 Kafka 및 Karafka 작업에 대해 더 많은 것을 배웠습니다. Honeybadger gem의 최신 버전으로 업데이트하지 않았다면 확인해 보세요! karafka 플러그인에 몇 가지 새로운 기능을 추가했습니다. Insights가 활성화되면 우리 gem은 Kafka 시스템의 전반적인 상태를 더 잘 볼 수 있도록 몇 가지 중요한 통계를 추적하기 시작합니다.
또한 이제 이 데이터를 시각화하고 Kafka 소비자의 행동 방식을 더 잘 이해할 수 있도록 도와주는 Insights Karakfa 대시보드가 있습니다. Karafka Dashboard에서는 플러그인에 대한 메트릭을 활성화해야 합니다. 그렇게 하려면 honeybadger.yml에 다음 구성을 추가하세요. :
karafka:
insights:
metrics: true
대시보드의 모습은 다음과 같습니다.

고객이 이 데이터를 사용하여 Kafka 시스템을 개선하는 방법을 보게 되어 기쁩니다. Sidekiq에서 Karafka로 마이그레이션한 방법이나 일반적인 Kafka 사용 방법에 대해 궁금한 점이 있으면 언제든지 문의해 주세요!