Large-Scale Automated Dependency Analysis Across Uber's Service Mesh
Bài tóm tắt Uber 2026 3. Quy mô lớn Độ khó: Khó
Uber · 2026 · 3. Quy mô lớn · Độ khó: Khó — bài gốc
Bài đầu của một cặp; bài sau dùng kết quả này để chặn retry storm: Uber 2026.
Bối cảnh
- Trong kiến trúc microservice của Uber, khi một request lỗi ở service gốc, khó biết phụ thuộc hạ nguồn nào gây ra; không thể trông vào service owner nhớ hết phụ thuộc (nhất là gián tiếp) vì chúng đổi liên tục. Biết phụ thuộc nào là fail-close (hỏng là kéo service gọi hỏng theo, lan tới gốc) và nào là fail-open cho phép alert theo phụ thuộc, tìm nguyên nhân gốc nhanh hơn, giảm alert gọi người, và chọn đường gọi đáng đầu tư.
- Vì sao không dùng tracing: lấy mẫu trace 0,01% và API có availability 99,9% thì xác suất lấy được một request lỗi là 1 trên 10 triệu; API 500 request/giây cần khoảng 5,5 giờ cho một mẫu lỗi, và khoảng 2 ngày 8 giờ cho 10 mẫu lỗi của một phụ thuộc (API có hàng trăm phụ thuộc), lúc đó đường gọi có thể đã đổi nhiều lần. Lấy mẫu toàn bộ quá đắt (hơn 99,9% request không lỗi); tail sampling (lỗi mới lấy) theo Uber không dễ làm và hạ tầng quá tốn.
- Proxy trên host (Muttley) có metric thành công/lỗi nhưng chỉ biết service gọi, không biết endpoint nào của service gọi đang xử lý, nên tương quan chỉ ở mức gộp, độ phân giải thấp.
Thay đổi chính
- Dùng metric, quan sát mọi lỗi: đổi tầm nhìn từng lỗi riêng lấy độ hội tụ nhanh. Đặt middleware trong yarpc (thư viện RPC của Uber cho Go, nay cả Java): middleware inbound gán một ID request (bộ đếm nguyên tử trong bộ nhớ) vào
context; ứng dụng truyền cùng context khi gọi hạ nguồn; middleware outbound đọc ID đó, nên mỗi lời gọi ra được gắn đúng với request vào đã kích nó. MộtRequestTrackerdùng chung bộ nhớ giữa hai middleware giữIngressLog(service + endpoint đang xử lý) và danh sáchEgressLog(service, endpoint đích, có lỗi không). Kết thúc request là có bức tranh đủ: request vào và mọi lời gọi ra. - Mô hình xác suất: với mỗi cạnh,
Pc= số request mà callee lỗi và caller cũng lỗi, chia cho số request mà callee lỗi.Pc ≥ 0,8là fail-close,≤ 0,2là fail-open, ở giữa là chưa rõ. Phân loại đường đi suy từ phân loại các cạnh. - Retry: không cho retry trong tầng ứng dụng; retry nằm ở một middleware outbound sau middleware phân tích, nên khi phân tích thấy kết quả thì mọi lần retry đã xong.
- Kết quả: đã lập danh mục phụ thuộc của mọi API quan trọng; phần lớn bất thường fail-close trên mesh đã được đánh chỉ mục, làm hàng rào chống hồi quy cho Failover Architecture 2.0; là nền cho cơ chế chống retry storm.
Vì sao
- Mẫu trace quá thưa để thấy lỗi hiếm trong thời gian hữu ích; đếm mọi lỗi ở middleware cho dữ liệu đủ dày và rẻ.
Bài học cho SWE
- Với sự kiện hiếm (lỗi), lấy mẫu thưa không đủ; đếm toàn bộ bằng metric có ngữ cảnh rẻ hơn lưu toàn bộ trace.
- Ngữ cảnh request (context) đi qua ứng dụng là cách nối lời gọi vào với lời gọi ra mà không cần tracing.
- Đặt retry ở một tầng cố định, sau tầng đo, để số liệu không bị retry làm nhiễu.
- Phân loại phụ thuộc bằng xác suất có vùng "chưa rõ", thay vì ép nhị phân.
Liên quan
- Tracing phân tán và log theo request · Độ tin cậy và multi-region
- Cùng công ty: Uber 2026 · Uber 2026 (middleware yarpc tốn stack)
- Cùng bài toán: Stripe 2019 (log có ngữ cảnh thay tracing)
#Dependency analysis#fail-close vs fail-open#hard dependency#call graph#trace sampling limits#tail sampling#yarpc middleware#request context#RequestTracker#ingress/egress log#probability model#Muttley#failover architecture
Được nhắc tới trong
Công ty (1)
Bài tóm tắt (1)