Tin tức

Cách Cloudflare mở rộng quy mô quét bảo mật lên 10 lần mà không phá vỡ Kafka

Cloudflare đã tái kiến trúc đường ống quét Security Insights để xử lý thông lượng gấp 10 lần, giải quyết tình trạng chặn đầu hàng trong Kafka, độ trễ cơ sở dữ liệu xuyên lục địa và bộ lập lịch không đều.

July 2, 2026· 4 min read· Nguồn: The Cloudflare Blog
Cách Cloudflare mở rộng quy mô quét bảo mật lên 10 lần mà không phá vỡ Kafka

Tính năng Security Insights của Cloudflare chạy các bản quét tự động trên mọi tài khoản khách hàng, vùng và bản ghi DNS để phát hiện cấu hình sai. Vấn đề? Các bản quét chạy mỗi tuần hoặc hai tuần một lần, và nhiều tài khoản miễn phí hoàn toàn không được quét. Để thu hẹp khoảng cách, nhóm cần tăng từ 10 bản quét mỗi giây lên 100 — tăng gấp 10 lần — trong khi hệ thống hiện tại đã quá tải với các lần hết thời gian chờ, tiến trình bị treo và hàng triệu sự kiện tồn đọng.

Kafka: không phải hàng đợi, nhưng đủ gần

Đường ống quét được kích hoạt bởi một bộ lập lịch gửi tin nhắn đến Apache Kafka. Các vi dịch vụ Go chuyên biệt (checker) tiêu thụ các tin nhắn đó và ghi kết quả vào cơ sở dữ liệu Postgres thông qua một API nội bộ. Mô hình phân vùng của Kafka có nghĩa là chỉ một consumer trên mỗi phân vùng trong mỗi nhóm consumer, và các tin nhắn phải được xử lý theo thứ tự trong một phân vùng. Điều đó tạo ra hai nút thắt cổ chai: tin nhắn chậm chặn consumer và số lượng consumer bị giới hạn bởi số lượng phân vùng.

Thay vì thêm phân vùng (điều này sẽ gây căng thẳng cho broker Kafka dùng chung), nhóm đã giới thiệu xử lý song song. Các checker hiện tiêu thụ tin nhắn theo lô và xử lý từng tin nhắn trong một goroutine riêng. Sự đánh đổi — nhiều công việc hơn phải làm lại khi bị treo, bộ nhớ cao hơn một chút — là chấp nhận được.

Làn nhanh, làn chậm

Một số bản quét mất vài phút hoặc vài giờ (tài khoản có hàng nghìn tài sản) trong khi hầu hết chỉ mất mili giây. Để tránh tình trạng chặn đầu hàng, nhóm đã chia mỗi checker thành hai nhóm consumer: một 'làn nhanh' và một 'làn chậm'. Làn nhanh bỏ qua các tin nhắn có vẻ tốn kém; làn chậm xử lý chúng với tài nguyên chuyên dụng. Đơn giản, hiệu quả.

Ghi cơ sở dữ liệu: từ 500.000 lượt truy vấn xuống mili giây

Mã gốc chèn từng insight bằng một câu lệnh SQL INSERT ... ON CONFLICT DO UPDATE riêng — lên tới 500.000 lượt truy vấn mỗi lần gọi API. Nhóm đã thử Postgres COPY vào một bảng tạm thời, nhưng điều đó gây phình to bảng hệ thống. Giải pháp kết hợp của họ: sử dụng UNNEST cho các lô nhỏ, COPY cho các lô lớn. Kết quả: các lần chèn mất vài giây cho tập lớn, mili giây cho tập nhỏ.

Độ trễ giết chết thông lượng

Cơ sở dữ liệu chính đặt tại Portland, Oregon, nhưng API chạy active-active ở cả Portland và Amsterdam. Ngay cả ở tốc độ ánh sáng, lượt truy vấn khứ hồi giữa Amsterdam và Portland mất thêm ~50ms. Điều đó nghe có vẻ không tệ, nhưng với khối lượng yêu cầu cao, nhóm kết nối ở Amsterdam nhanh chóng cạn kiệt, gây ra hết thời gian chờ. Tệ hơn, các phân vùng Kafka được gán cho các tiến trình consumer ở Amsterdam bị tụt hậu nghiêm trọng — chính xác một nửa số phân vùng bị chậm. Giải pháp: chuyển API sang active-passive, định tuyến tất cả lưu lượng đến instance Portland. Độ trễ giảm từ ~3 giây xuống ~10ms.

Bộ lập lịch: ngăn chặn cơn lũ

Bộ lập lịch gốc lặp qua các tài khoản có last_scheduled_at + frequency <= now. Vì nhiều tài khoản có cùng last_scheduled_at, các bản quét đến thành các đợt lớn. Các tài khoản lớn với nhiều vùng gây ra lũ quét theo tầng. Nhóm đã thực hiện ba thay đổi: lập lịch các vùng độc lập (mỗi vùng có last_scheduled_at riêng), ngẫu nhiên hóa dấu thời gian ban đầu cho các tài khoản và vùng hiện có, và thêm giới hạn tốc độ thích ứng cho việc lập lịch. Các bản quét hiện được trải đều theo thời gian.

Kết quả: tăng thông lượng gấp 10 lần, quét tự động được kích hoạt cho hàng triệu tài khoản và tần suất quét tăng gấp đôi cho mọi người. Không cần phân vùng mới, không cần phần cứng mới — chỉ là kỹ thuật cẩn thận.