This Rocket Ain't Stopping - Achieving Zero Downtime for Rails to Golang API Migration

Bài tóm tắt Grab 2016 2. Tăng trưởng Độ khó: Trung bình

Grab · 2016 · 2. Tăng trưởng · Độ khó: Trung bình — bài gốc

Bối cảnh

  • Grab đang chuyển từ Rails + NodeJS sang kiến trúc service toàn Go. Một phần mục tiêu là về tổ chức: chuyển các kỹ sư Rails sang các team Go, chung một codebase.
  • Một team API mới nhận nhiệm vụ chuyển hơn 30 endpoint public của app hành khách sang server Go, rồi trỏ DNS sang cluster Go.

Thay đổi chính

  • Quy tắc: mỗi endpoint phải qua unit test, load test, QA staging, shadow test trên production; deploy từng endpoint một, tăng dần, rollback được ngay.

  • Hướng đi bị bỏ: ban đầu muốn chiếm DNS trước bằng một proxy Go mỏng trước bản clone Rails, gọi qua gRPC. Gặp liên tiếp:

    • ELB không hỗ trợ HTTP/2 nên phải cân bằng TCP, dẫn tới lệch tải khi auto-scale. Họ chữa bằng script restart Go dần.
    • Gem gRPC của Ruby rò bộ nhớ (họ còn gửi PR sửa).
    • Latency đo hai đầu không khớp.

    Sau ~1 tháng họ bỏ hẳn hướng này và chuyển logic thật sang Go. Nhân tiện tách một số module thành service riêng cho các team khác nhau sở hữu.

  • Load test: phát lại log của ngày đông nhất trong tháng vào staging.

  • Shadow test: Rails xử lý như bình thường rồi gửi bản sao request + response sang Go; Go tự xử lý và so sánh bằng một JSON tokenizer tự viết. Lệch thì báo vào statsd và Slack.

    • Với PUT/POST/DELETE: bọc DAO bằng mock, chỉ tính hàng DB dự kiến rồi so với hàng thật, để không ghi đôi.
    • Lệch do trạng thái booking đổi giữa hai lần xử lý: hiếm, kiểm tra bằng tay.
  • Tăng shadow theo RPS, không theo %: 1% của một endpoint lớn đã hơn toàn bộ 5 endpoint khác cộng lại, từng làm ELB từ chối request. Họ cũng báo AWS "làm nóng" ELB trước.

  • Roll out từng endpoint theo RPS bằng cùng cơ chế, cuối cùng mới đổi DNS.

Vì sao

Theo Grab: một codebase Go chung cho toàn công ty; đổi DNS một lần cho 30+ endpoint đòi hỏi bản Go phải hoàn hảo ngay lập tức, điều không thực tế.

Bài học cho SWE

  • Shadow traffic + so sánh tự động là cách kiểm chứng logic mới bằng traffic thật mà không ảnh hưởng user.
  • Shadow cho lệnh ghi cần cơ chế riêng (mock DAO) để không ghi đôi.
  • Phần trăm vô nghĩa nếu không biết tải tuyệt đối. Hãy điều khiển theo RPS.
  • Dám bỏ một tháng công khi hướng đi sai.

Liên quan