Scaling Security Insights: how we achieved a 10x increase in global scanning capacity
Bài tóm tắt Cloudflare 2026 3. Quy mô lớn Độ khó: Trung bình
Cloudflare · 2026 · 3. Quy mô lớn · Độ khó: Trung bình — bài gốc
Bối cảnh
- Security Insights quét định kỳ mọi account, zone, bản ghi DNS để tìm cấu hình sai. Hai vấn đề: quét 1–2 tuần một lần, và nhiều account free phải tự bật mới được quét.
- Muốn quét thường hơn và bật cho mọi account thì thông lượng phải tăng khoảng 10 lần, từ 10 lên 100 lượt quét/giây. Trong khi đó hệ đã đuối: hàng triệu event tồn đọng, API nội bộ hay timeout, tiến trình crash.
- Kiến trúc: scheduler đẩy message vào Kafka → fan-out tới các checker (microservice Go, mỗi loại kiểm một thứ, mỗi loại một consumer group) → checker gửi kết quả về API nội bộ → ghi vào Postgres.
Thay đổi chính
- Xử lý song song trong partition: Kafka chỉ cho một consumer mỗi partition trong một consumer group, và phải xử lý theo thứ tự. Thêm partition thì tốn tài nguyên broker dùng chung với nhiều service khác, nên để làm cách cuối. Thay vào đó, checker đọc theo lô và xử lý mỗi message trong một goroutine; đổi lại crash giữa lô thì làm lại nhiều hơn và tốn thêm chút bộ nhớ.
- Làn nhanh và làn chậm: vài message (account rất nhiều tài sản) mất vài phút tới vài giờ so với mili giây của trường hợp thường, chặn cả partition (head-of-line blocking). Tách mỗi checker thành hai consumer group; làn nhanh gặp message chậm thì bỏ qua cho làn chậm xử lý.
- Ghi theo lô vào Postgres: endpoint ghi kết quả lặp
INSERT ... ON CONFLICT DO UPDATEtừng dòng, có lần tới 500.000 dòng trong một lời gọi API, tức nửa triệu round-trip và transaction.COPYvào bảng tạm làm phình bảng hệ thống của Postgres, nên chọn cách lai: dưới một ngưỡng dùngUNNEST, trên ngưỡng dùngCOPY. Lô nhỏ còn vài mili giây, lô khổng lồ vài giây. - API đi theo database: database chính ở Portland, API chạy active-active ở Portland và Amsterdam. RTT Portland–Amsterdam khoảng 50 ms giữ kết nối lâu, cạn connection pool phía client: gọi API trung bình 10 ms ở Portland, gần 3 giây ở Amsterdam. Vì checker giữ kết nối suốt đời tiến trình và load balancer chia đều, đúng 15 trên 30 partition lag. Chuyển API sang active-passive, bản active đi theo database chính; vấn đề latency hết "sau một đêm".
- Scheduler rải đều: scheduler cũ chạy lặp "tìm account có
last_scheduled_at + chu kỳ <= now, quét account và mọi zone của nó". Hàng trăm nghìn lượt quét có lúc dồn trong vài phút vì nhiều account cólast_scheduled_atgần nhau; đổi chu kỳ từ 15 xuống 7 ngày thì 53% account đến hạn cùng lúc; account nhiều zone sinh thác quét làm bão hoà partition. Topic Kafka giữ theo thời gian, nên dồn quá nhiều thì message bị xoá trước khi xử lý. Ba sửa đổi: lập lịch zone độc lập với account; ngẫu nhiên hoálast_scheduled_athiện có; rate limit thích ứng, tính lại mỗi nửa giờ từ số account/zone theo gói chia cho chu kỳ quét của gói, nhân một hệ số dự phòng, tối thiểu 1 lượt/giây.
Kết quả (2026)
- Thông lượng mỗi checker (trung bình 7 ngày) tăng hơn 10 lần; đỉnh hơn 120 lượt quét/giây. API hết timeout, Kafka lag lành.
- Bật quét tự động cho mọi account free; chu kỳ: free 7 ngày, Pro/Business 3 ngày, Enterprise hằng ngày; thêm quét theo yêu cầu.
Vì sao
- Theo Cloudflare, họ đã cân nhắc thêm tài nguyên, thêm partition, thậm chí bỏ cả kiến trúc; bài học là hiểu sâu hệ hiện có (code, SQL, log, nhất là metric) trước khi vứt đi, và không lấy đường tắt như tăng timeout phía client.
Bài học cho SWE
- Kafka là log có thứ tự, không phải queue: độ song song bị giới hạn bởi số partition, và một message chậm chặn cả partition. Xử lý song song trong lô và tách làn theo chi phí là hai cách trước khi thêm partition (Event-driven, message queue và Kafka).
- Vòng lặp ghi từng dòng là nút thắt quen thuộc; ghi theo lô, và chọn cơ chế theo kích thước lô (Batching và khấu hao round-trip).
- Active-active cho tầng không trạng thái nhưng database chỉ ở một nơi thì nửa số request trả RTT xuyên đại dương; tầng gần dữ liệu nên đi theo primary (Độ tin cậy và multi-region).
- Lịch "đến hạn thì chạy" tự tạo đỉnh: đồng bộ ngẫu nhiên giữa các bản ghi, đổi chu kỳ, thác con; rải bằng jitter và giới hạn tốc độ tính từ tổng khối việc (Hot partition và thundering herd). Cùng mẫu với GitLab 2019.
Liên quan
Event-driven, message queue và KafkaHot partition và thundering herdBatching và khấu hao round-tripĐộ tin cậy và multi-region
#Kafka#Consumer group#Partition#Head-of-line blocking#Fast lane/slow lane#Postgres#UNNEST#COPY#Connection pool#Active-passive#Scheduler#Adaptive rate limiting#Go
Được nhắc tới trong
Chủ đề (4)
Công ty (1)