Building an Effective Test Pipeline in a Service Oriented World

Bài tóm tắt Airbnb 2020 3. Quy mô lớn Độ khó: Trung bình

Airbnb · 2020 · 3. Quy mô lớn · Độ khó: Trung bình — bài gốc

Bối cảnh

  • Airbnb đang chuyển từ một ứng dụng Rails khổng lồ sang SOA. Các luồng nghiệp vụ quan trọng từng nằm trong monorepo nay nằm ở nhiều service: REST + DB, Kafka producer/consumer, job hẹn giờ.
  • Yêu cầu: user không thấy gì khác; không có thay đổi xấu lên production; nhưng vẫn giữ được năng suất (một lý do chính để chuyển sang SOA).
  • Pipeline cũ: một project "deep integration test" chạy mọi test cho mọi service liên quan, trước khi merge, mỗi commit. Mỗi lần chạy dựng toàn bộ service trong môi trường dev riêng. Lý do: chưa có pipeline deploy kiểm soát thứ tự, nên master xấu có thể lên thẳng production.

Vấn đề khi số service và test tăng

  • CI ngày càng chậm, flaky (nhiều phụ thuộc đồng bộ lẫn bất đồng bộ).
  • Viết và debug test rất lâu (một test chạm nhiều service, không biết xem log ở đâu).
  • Phản hồi chậm (đợi lâu mới biết chỉ là một service không khởi động được vì config sai).
  • Khó scale; ngược với tháp test, vì khuyến khích viết nhiều test nặng ở đỉnh.
  • Không có kiểm chứng ở bước CD, nên vô tình khuyến khích "test trên production".

Thay đổi chính

Pipeline mới chia CI và CD, theo tháp test:

  • CI (Buildkite): unit test + shallow integration test, kiểm tra một service với mọi phụ thuộc bị mock bằng fixture YAML (cặp request/response + luật khớp). Chỉ chạy khi chính service đó đổi.
  • CD (Spinnaker): deploy theo thứ tự qua staging dùng chung, chạy deep integration test (số lượng ít hơn), rồi Automatic Canary Analysis sau khi lên canary. Có pipeline khẩn cấp đi thẳng production, chỉ cho bản vá gấp.
  • Hai quy tắc: test cấp cao bắt được lỗi mà không test cấp thấp nào hỏng thì phải viết thêm test cấp thấp; đẩy test xuống thấp nhất có thể.

Kết quả (theo Airbnb)

Mỗi service có pipeline riêng nên thêm service không ảnh hưởng pipeline khác; ít flaky hơn; merge nhanh hơn; độ phủ tốt hơn vì viết được nhiều test nhỏ. Bài không có số liệu.

Bài học cho SWE

  • Chi phí test là một chi phí ẩn của SOA. Test "mọi thứ cùng lúc" trước merge không scale theo số service. Segment gặp cùng vấn đề (Segment 2018) nhưng giải theo cách khác: gom về một service và dùng Traffic Recorder.
  • Mock phụ thuộc bằng fixture ghi sẵn cho test mức service, giống ý tưởng Traffic Recorder.
  • Đẩy kiểm chứng nặng sang CD (staging + canary analysis) thay vì chặn ở trước merge. Xem Deploy và release an toàn.

Liên quan