Counter Service: How we rewrote it in Rust
Grab · 2025 · 4. Điều chỉnh · Độ khó: Trung bình — bài gốc
Bối cảnh
-
Phần lớn microservice của Grab viết bằng Go, nằm trong một monorepo. Rust vào dần: vài CLI, rồi một reverse proxy cho model serving (Catwalk). Câu hỏi tiếp theo là ROI của việc viết lại một service Go.
-
Tiêu chí chọn service (theo Grab):
- đơn giản (một hai chức năng chính, viết lại được trong thời gian hợp lý);
- traffic đủ lớn để tiết kiệm chi phí là đáng kể;
- team sẵn lòng học Rust, để không phụ thuộc vào một người duy nhất.
Viết lại "chỉ để dùng Rust" không phải lý do kinh doanh đủ mạnh.
-
Counter Service (team Integrity): đọc stream, đếm event, ghi vào ScyllaDB; endpoint gRPC
BatchReadphục vụ tới hàng chục nghìn QPS lúc cao điểm.
Thay đổi chính
- Không dịch từng dòng (Go viết theo kiểu Go chưa chắc là Rust tốt). Họ coi service là hộp đen: viết lại từ đầu theo contract gRPC và dữ liệu trong Scylla, nhắm tới output gần như giống hệt.
- Kiểm tra thư viện: có đủ (tonic, scylla-rust-driver, fred.rs…), nhưng vài thư viện ít sao/không chính thức. Thư viện Redis "chính thức" không đáp ứng được nên đổi sang fred.rs.
- Thư viện nội bộ chỉ có cho Go (config dựa trên Go template, chèn secret). Họ tự viết parser tương đương bằng nom.
- Trở ngại:
- borrow checker ít khó hơn dự kiến (lúc đầu cứ clone thoải mái, sau mới profile bằng flamegraph);
- async là chỗ dễ vấp: lỡ gọi Redis bằng hàm đồng bộ (blocking) trong code async làm hiệu năng rất tệ, cho tới khi đổi sang bản non-blocking.
- Kiểm chứng bằng shadow traffic cho cả hai service.
Kết quả (2025)
| QPS chuẩn hoá | Tài nguyên | |
|---|---|---|
| Bản Go | 1.000 | 20 core |
| Bản Rust | 1.000 | 4,5 core |
p99 tương đương, có khi còn hơi kém hơn bản Go. Tức là không nhanh hơn, nhưng rẻ hơn ~5 lần (Grab tóm tắt là tiết kiệm ~70–80%).
Vì sao
Theo Grab: hiệu quả tài nguyên ở một service nhiều traffic. Kết luận của họ:
- "Rust nhanh hơn Go": sai (Go đủ nhanh);
- "Rust hiệu quả hơn": đúng;
- "Rust khó học": tuỳ, sync dễ, async khó.
Họ khuyến khích chọn Rust cho service mới, với điều kiện đầu tư đào tạo.
Bài học cho SWE
- Chọn ứng viên viết lại bằng tiêu chí rõ ràng: đơn giản, traffic lớn, team sẵn sàng.
- Viết lại theo contract (hộp đen) + shadow traffic, cùng tinh thần Grab 2016 (Grab 2016).
- Lợi ích có thể nằm ở chi phí chứ không ở latency. Discord 2020 thì ngược lại, viết lại vì spike latency do GC (Discord 2020).
- Hệ sinh thái nội bộ (thư viện config, secret) là chi phí ẩn khi rời ngôn ngữ chính của công ty.