최근 Cloudflare는 모든 계정의 보안 리스크를 탐지하는 'Security Insights'의 스캔 성능을 10배 이상 향상시킨 기술적 여정을 공유했습니다. 초당 10회에서 100회로 스캔 처리량을 늘리면서, 기존 시스템이 직면했던 백로그 적체와 API 타임아웃 문제를 어떻게 해결했는지 기술적 관점에서 분석합니다.
주요 과제: 주 단위로 이루어지던 스캔 주기를 단축하고, 수백만 개의 무료 계정까지 자동 스캔 범위를 확대하기 위한 인프라의 확장성 확보
1. Kafka 소비 아키텍처의 재설계
Cloudflare의 스캔 아키텍처는 스케줄러가 Apache Kafka로 메시지를 발행하고, Go로 작성된 마이크로서비스(Checkers)가 이를 소비하는 구조입니다. 하지만 Kafka의 파티션 구조상 한 파티션 내에서는 순차적 처리가 강제되므로, 처리 속도가 느린 메시지가 전체 파이프라인을 점유하는 'Head-of-Line Blocking' 문제가 발생했습니다.
이를 해결하기 위해 개발팀은 두 가지 전략을 도입했습니다:
- 고루틴(Goroutine) 기반의 배치 처리: 메시지를 하나씩 처리하는 대신 배치 단위로 소비하고, 각 메시지를 별도의 고루틴에서 병렬로 실행하여 처리 속도를 극대화했습니다.
- Fast Lane과 Slow Lane의 분리: 처리 시간이 긴 대형 계정과 짧은 계정을 식별하여 소비자 그룹을 분리했습니다. 이를 통해 무거운 작업이 가벼운 작업의 발목을 잡는 현상을 방지했습니다.
2. 데이터베이스 쓰기 성능의 혁신
기존 시스템의 가장 큰 병목 중 하나는 PostgreSQL 저장 로직이었습니다. 초기 코드는 발견된 보안 인사이트 하나당 한 번의 DB 라운드 트립을 수행하는 비효율적인 구조였습니다. 최대 50만 건의 데이터가 발생할 수 있는 상황에서 이는 치명적이었습니다.
팀은 이를 해결하기 위해 하이브리드 벌크 인서트 전략을 선택했습니다:
- 데이터 양이 적을 때는 UNNEST 기능을 사용하여 배열 형태로 한 번에 쿼리.
- 데이터 양이 임계치를 넘을 때는 PostgreSQL의 COPY 명령을 사용하여 대량의 데이터를 효율적으로 삽입.
아키텍트의 분석
이번 Cloudflare의 사례는 단순한 인프라 증설이 아닌, 컴퓨팅 자원의 효율적 배분과 I/O 밀도 최적화가 핵심입니다. 특히 Kafka를 단순한 큐로 보지 않고 파티셔닝의 특성을 이해하여 Go의 동시성 모델로 극복한 점이 인상적입니다.
또한, 데이터베이스 계층에서의 'N+1 Query' 문제는 분산 시스템에서 가장 흔하면서도 치명적인 병목입니다. UNNEST와 COPY를 적절히 섞어 사용하는 하이브리드 방식은 데이터의 가변성이 큰 보안 스캔 환경에서 성능과 안정성을 모두 잡을 수 있는 영리한 접근 방식입니다. 엔지니어링 측면에서 볼 때, '코드 수준의 최적화가 시스템 전체의 확장성을 어떻게 결정짓는가'를 보여주는 아주 좋은 교과서적 사례라고 평가합니다.
원문 출처: Scaling Security Insights: how we achieved a 10x increase in global scanning capacity
댓글
댓글 쓰기