Troubleshooting: A journey into the unknown
Bài tóm tắt Booking.com 2017 3. Quy mô lớn Độ khó: Khó
Booking.com · 2017 · 3. Quy mô lớn · Độ khó: Khó — bài gốc
Bối cảnh
- Distributed Load Balancing (DLB) của Booking: các server nối thẳng Internet, dual-home, peer BGP với switch hai phía, chia traffic bằng ECMP; anycast-healthchecker rút route khi service hỏng; BFD gửi hello UDP mỗi 400 ms, mất ba gói liên tiếp (1,2 giây) thì phiên bị coi là chết.
- Triệu chứng: traffic vào một member tụt về 0 trong một chu kỳ lấy mẫu (metric mỗi 10 giây) rồi hồi sau khoảng 50 giây; các member khác gánh đều nhờ ECMP. Xảy ra ngẫu nhiên trên nhiều server mỗi ngày.
Thay đổi chính
- Thu hẹp nguyên nhân: log của Bird cho thấy switch reset phiên BGP vì thiếu ba hello BFD, trên cả hai card mạng tới hai switch khác nhau cùng lúc, nên lỗi nằm ở host. Loại trừ tấn công (không tăng TCP/ICMP/HTTP, UDP bị chặn), loại trừ cấu hình haproxy và phiên bản.
- Dấu vết: cùng lúc có CPU 100% ở mức system trên cả 10 process haproxy, và hệ điều hành bỗng giải phóng khoảng 600 MB bộ nhớ. Gắn script ghi pidstat, sar, ss, strace mỗi giây (vì lỗi chỉ cần 1,2 giây) trên vài server rồi chờ; một lần dính lỗi thu khoảng 150 MB, gần 10 triệu dòng log. Trong lúc chờ: ghim Bird sang CPU không dùng cho haproxy, nice -17, giảm ưu tiên CPU của puppet.
- Cùng Willy Tarreau (tác giả haproxy) phân tích: máy đã cấp 92% bộ nhớ (gồm cache), rồi giải phóng page cache khoảng 600 MB/giây trong khoảng 6 giây, khoá mọi CPU khoảng 8 giây; haproxy dừng giữa syscall vì chạm vùng nhớ vừa bị thu hồi (minor page fault). CPU cao của haproxy là triệu chứng, không phải nguyên nhân.
- Nguyên nhân gốc: máy 96 GB nhưng bộ nhớ hoạt động chỉ khoảng 8 GB; dentry cache phình tới 80 GB vì
vm.vfs_cache_pressure=100không thu hồi mạnh. Thủ phạm là curl: với HTTPS, thư viện NSS gọiaccesstới các file không tồn tại tên ngẫu nhiên mỗi lần chạy, sinh dentry mới. Chính health check của anycast-healthchecker gọi curl mỗi 10 giây cho khoảng 10 service, cộng một cron job. - Sửa tạm bằng
drop_cachesvàvfs_cache_pressure200 → 1000; sửa gốc bằng biến môi trườngNSS_SDB_USE_CACHE=YEScho mọi check dùng curl; số dentry ngừng tăng.
Vì sao
- Một lỗi 1,2 giây mất hẳn hai đường BGP chỉ lộ khi tách được chuỗi nguyên nhân: tiến trình phụ (health check) → cache kernel → thu hồi bộ nhớ dồn dập → mọi CPU bận → daemon routing lỡ hello.
Bài học cho SWE
- Theo Booking: độ phân giải của metric quyết định thấy được lỗi hay không. Mẫu 10 giây vừa đủ thấy; mẫu 1 phút trên hệ khoảng 50 nghìn request/giây thì "bay mù" với lỗi ngắn hơn một phút.
- Thứ gây sự cố có thể là công cụ giám sát chạy trên chính máy đó; nhìn cả tiến trình phụ và cron, không chỉ ứng dụng chính.
- Đặt tiến trình giữ liveness (routing daemon) trên CPU riêng, ưu tiên cao, để nó không chết theo tải của ứng dụng.
- ECMP xáo lại kết nối khi một member rời rồi vào lại nhóm ít ảnh hưởng hơn họ tưởng.
Liên quan
- Sự cố và postmortem · Observability và monitoring
- Booking.com 2017 · GitLab 2019 (tải do chính hệ thống tạo) · Mercari 2025
#load balancer#ECMP#BGP#BFD#Bird#anycast-healthchecker#haproxy#dentry cache#page cache#vfs_cache_pressure#curl NSS#độ phân giải metric
Được nhắc tới trong
Công ty (1)