- 이벤트를 저장하고 여러 서비스가 각자의 속도로 처리하도록 하는 서버리스 서비스로, Cloudflare가 공개 베타를 출시함. 주문 완료 이벤트를 분석과 부정 거래 탐지 시스템에 함께 전달하는 데 활용 가능
- 클러스터를 직접 운영하거나 확장할 필요 없이, R2 객체 스토리지를 기반으로 대량의 이벤트와 과거 데이터를 저비용으로 보관함
- 하나의 구독에서는 여러 소비자가 작업을 나눠 처리하고, 별도 구독을 만들면 각 서비스가 같은 이벤트 전체를 독립적으로 읽을 수 있음
- 개별 작업의 재시도에 초점을 맞춘 Queues와 달리 대량 데이터 전달과 장기 보관에 적합함. 배치 단위로 처리하며, 초기 버전의 쓰기 요청 지연은 p99 기준 약 1초임
- Workers 유료 구독 계정에서 베타 기간 추가 과금 없이 이용할 수 있음. 초기 한도는 저장 공간 10GB, 스트림당 쓰기 처리량 30MB/s이며 Kafka 클라이언트 호환은 향후 지원 예정
- 전통적인 RPC 구조에서는 생산자와 소비자가 처리 규모와 시점에 맞춰 동작해야 함
- 생산자가 소비자의 처리 능력을 초과하는 데이터를 보내거나 소비자 또는 하위 서비스가 중단되면 이벤트가 유실됨
- 전자상거래의 거래 완료 이벤트를 분석 시스템과 부정 거래 탐지 서비스가 각각 처리하는 것처럼, 독립적인 소비자가 여럿이면 문제가 더 복잡해짐
- K2는 쓰기를 받아 저장하는 중간 계층을 두고, 독립적인 소비자가 자신의 속도로 읽도록 함
- Developer Platform의 완전한 서버리스 이벤트 스트리밍 기능으로, 이벤트를 순서형 로그에 저장함
- 대규모 데이터와 장기 보관을 지원해 소비자가 장시간 중단되더라도 데이터를 잃지 않도록 함
- 시작 가이드를 통해 스트림을 생성할 수 있음
- K2는 처음에 Basin Pipelines 의 수집 계층을 위한 내구성 있는 엣지 버퍼로 개발됨
- Pipelines의 스트림 처리 엔진은 풀 기반으로 동작하므로, 이벤트를 읽고 변환해 R2에 쓰기 전까지 별도 시스템이 보관해야 함
- Pipelines Stream이 수락한 이벤트를 유실하지 않겠다는 보장을 지키려면 장기간에도 데이터가 사라지지 않는 저장소가 필요함
- 일반적으로는 Apache Kafka를 배포할 수 있지만, 335개가 넘는 도시에 걸친 Cloudflare 엣지 환경에서는 기존 분산 시스템 소프트웨어를 그대로 운영하기 어려운 경우가 많음
- 상태 저장 서비스는 머신 자원의 작은 몫만 사용하며, 머신은 비교적 수명이 짧고 네트워크 통신은 공용 인터넷을 거치는 경우가 많음
- 반면 전 세계 사용자와 가깝고 수평 확장 능력이 크다는 장점이 있음
- R2는 11개의 9로 표현되는 내구성과 강한 일관성 API를 제공함
- 복제와 합의를 스토리지 계층에 맡겨 K2 애플리케이션 계층을 단순화하고 비용과 성능을 개선함
- 컴퓨팅과 스토리지를 분리해 각각 독립적으로 확장하고, 방대한 과거 데이터를 저비용으로 저장할 수 있음
- R2를 비롯한 객체 스토리지는 로그의 기본 연산인 덧붙이기(append) 를 지원하지 않으므로, 완전한 파일 또는 세그먼트 단위로 써야 함
- 각 파일의 쓰기와 읽기 비용을 상쇄할 만큼 충분한 크기로 묶어야 함
- 엣지 서비스의 메모리에 쓰기를 모으고 잠시 기다린 뒤, 누적된 이벤트를 하나의 세그먼트 파일로 기록함
- R2의 원자적 연산으로 이벤트 순서와 엄격히 증가하는 오프셋을 구현하며, 별도 조정 서비스는 필요하지 않음
- 객체 스토리지 쓰기는 로컬 디스크보다 느리고 배치가 쌓이기를 기다려야 하므로 생산 지연이 커짐
- 초기 K2 버전의 생산 요청 지연은 응답 시간 99백분위에서 약 1초임
- Cloudflare는 후속 기술 심층 글에서 설계 세부 사항을 공개할 예정임
- Queues 는 비용이 크거나 시간이 오래 걸리는 개별 작업을 비동기로 완료하고 추적하는 용도에 적합함
- 이미지 처리 요청을 큐에 넣고 실제 처리 서비스가 수행하는 방식이 대표적임
- 작업 항목별 재시도, 지연, 실패한 작업을 위한 데드 레터 큐를 지원함
- K2는 대규모 데이터 이동, 장기 보관, 여러 소비자로의 배포에 초점을 맞춤
- 메시지를 배치 단위로 생산하고 소비해 효율적으로 처리하지만, 메시지 단위 재시도는 지원하지 않음
- 배치 처리 때문에 생산 지연도 Queues보다 큼
- Basin Pipelines 는 JSON 이벤트를 받아 변환한 뒤 R2 또는 Basin Catalog에 기록하는 서버리스 수집 서비스임
- 최종 목적지가 객체 스토리지나 Iceberg 테이블이라면 Pipelines를 권장함
- 사용자 정의 처리를 수행하거나 다른 목적지에 기록하려면 K2를 권장함
- 계정 내에서 용도나 이벤트 유형별로 여러 스트림을 만들 수 있으며, cf, Wrangler, 대시보드, API로 생성할 수 있음
- 제품 분석 예제에서는 cf k2 streams create --name app_events --http-enabled로 스트림을 생성함
- 예제 응답의 보관 기간은 604800초, 즉 7일이며 HTTP 엔드포인트와 Worker 바인딩이 활성화되어 있음
- 이벤트는 HTTP API 또는 Worker 바인딩으로 전송함
- Worker 예제는 env.EVENTS.send로 page_view 이벤트, 요청 경로, 타임스탬프를 JSON으로 인코딩해 보냄
- 전송 실패 시 오류를 기록하고, 재시도 가능한 오류에는 HTTP 503, 그 외에는 500을 반환함
- K2는 데이터를 바이트로 취급하므로 애플리케이션에 적합한 형식과 인코딩을 사용할 수 있음
- 구독(subscription) 은 소비자 사이에 작업을 분배해 읽기를 병렬화하고, 단일 서버가 감당할 수 있는 수준을 넘어 확장하도록 함
- 예제는 HTTP API로 analytics_processor 구독을 만들고 start_at을 earliest로 지정함
- 각 소비자는 worker_id를 지정해 구독을 폴링하며, 예제의 max_records는 100임
- 클라이언트가 consume을 호출하면 해당 이벤트 배치에 대한 5분짜리 임대(lease) 를 받으며, 다음 세 가지 작업을 할 수 있음
- ack: 배치를 처리 완료로 표시하고 재전달되지 않도록 함
- nack: 처리 실패를 알리고 재전달을 요청함
- extend: 처리 시간이 더 필요할 때 임대를 연장함
- 소비 구성은 작업 분배와 전체 메시지 수신을 모두 지원함
- 하나의 구독을 여러 소비자가 공유하면 각 소비자가 데이터 일부를 처리함
- 소비자별로 별도 구독을 만들면 발행/구독 패턴으로 각 소비자가 모든 메시지를 받음
- 두 방식을 조합해 여러 독립적인 소비자 풀을 구성할 수 있음
- 전체 API 세부 사항은 K2 문서 에서 확인할 수 있음
- Workers Paid 구독 계정에서 공개 베타를 사용할 수 있으며, 사용 한도는 저장 공간 최대 10GB와 스트림당 생산 처리량 30MB/s임
- 더 높은 한도가 필요하면 Discord에서 팀에 문의하거나 한도 상향 요청 양식을 제출할 수 있음
- 베타 기간에는 과금하지 않으며, 과금 시작 후 예상 요금은 다음과 같음
- 생산 데이터는 GB당 0.04달러임
- 소비 데이터는 GB당 0.04달러임
- 보관 데이터는 월 GB당 0.02달러임
- 향후 수개월간 쓰기 병렬성을 높여 초당 수 GB 수준의 스트림을 지원할 계획임
- 메시지 키와 키 기반 순서 보장을 추가할 예정임
- 푸시 기반 Worker 소비자를 지원할 계획임
- 생산 지연과 종단 간 지연을 낮춘 Express 등급을 준비 중임
- Apache Kafka 클라이언트를 그대로 사용할 수 있는 호환 지원을 계획하고 있으며, 피드백은 Cloudflare Discord에서 받음