Centralized Application Logging at eBay (CAL Ingress)

Bài tóm tắt eBay 2019 3. Quy mô lớn Độ khó: Khó

eBay · 2019 · 3. Quy mô lớn · Độ khó: Khó — bài gốc

Bối cảnh

  • CAL gom log cục bộ của các application server về một chỗ và làm báo cáo cho mọi mảng của eBay. CAL Ingress nhận log từ hàng nghìn client qua kết nối TCP sống lâu, chia ra: raw log tới Filer, metric VID (gộp lại) qua Kafka tới OLAP, heartbeat tới kho metric.
  • Quy mô: khoảng 2,5 PB log mỗi ngày, trung bình 105 TB/giờ (29,87 GB/s), đỉnh 58 GB/s; khoảng 1 triệu kết nối đồng thời.
  • Yêu cầu latency: nếu client không gửi được một lô trọn vẹn, kết nối bị coi là hỏng và dữ liệu đệm ở cả hai phía bị bỏ ("TCP disconnect" = mất dữ liệu). Buffer mạng client 128 KB, trung bình 200 KB/s mỗi kết nối, nên Ingress phải đọc kịp trong dưới 0,64 giây. Latency mỗi kết nối ≈ (số kết nối / số thread) × chu kỳ đọc + thời gian dừng GC.

Thay đổi chính

  • Đọc không ngừng: bật TCP_NODELAY, TCP_QUICKACK; tách đọc và xử lý vào hai EventLoopGroup Netty riêng (vài thread chỉ đọc socket vào direct memory rồi đọc tiếp). Số TCP disconnect của một pool từ 2.500–21.000 (thế hệ trước) xuống 4–65.
  • Giảm GC (G1GC): dữ liệu nhận chép thẳng vào bộ nhớ off-heap cấp sẵn thay vì tạo object trên heap; tăng vùng young (G1NewSizePercent=50) vì đa số object sống ngắn; heap dump cho thấy 62,82% object là SlicedByteBuf sinh ra trong một hàm, viết lại hàm đó; dùng thread pool thay vì tạo thread mỗi lần để giảm tranh CPU của GC worker.
  • Xử lý nhanh hơn tốc độ đọc (không thì direct memory đầy và OOM): viết lại hàm tìm trong ByteBuf đọc nhiều byte mỗi lần (−30% thời gian); gom gói nhỏ tới 160 KB rồi mới nén (số lần nén còn 1/10); ghi lười xuống Filer chậm qua ring buffer kích thước cố định trong direct memory, đầy thì bỏ dữ liệu mới đến.
  • Hệ thống: zlib của Cloudflare, RSS và ghim NUMA, kiểm off-CPU để bớt context switch.
  • Kết quả: một Ingress phục vụ 1.000 kết nối đạt 220 MB/s không có TCP disconnect.

Vì sao

  • Với pipeline log, latency đọc của server là độ bền của dữ liệu: đọc chậm (vì xử lý hay GC) làm client bỏ dữ liệu (Observability và monitoring).
  • Nén và ghi theo lô thay vì từng gói nhỏ khấu hao chi phí cố định mỗi lần nén/ghi (Batching và khấu hao round-trip).

Bài học cho SWE

  • Tách thread đọc mạng khỏi thread xử lý nặng khi phía gửi có buffer nhỏ.
  • Với JVM ở throughput cao, off-heap và giảm số object sống sót là đòn bẩy chính; đo bằng heap dump trước khi chỉnh.
  • Giới hạn bộ nhớ đệm và định trước chính sách bỏ dữ liệu khi đích chậm: pipeline quan sát được phép mất dữ liệu có kiểm soát.

Liên quan