Atlas: Our journey from a Python monolith to a managed platform

Bài tóm tắt Dropbox 2021 4. Điều chỉnh Độ khó: Trung bình

Dropbox · 2021 · 4. Điều chỉnh · Độ khó: Trung bình — bài gốc

Bối cảnh

  • Metaserver, monolith Python từ 2007, hơn 3 triệu dòng; khoảng một nửa commit vào repo server sửa nó. Mô hình "hệ mặt trời": tính năng sản phẩm nằm trong monolith, các thành phần nền (xác thực, metadata, filesystem, sync) đã tách thành service. Hơn 700 triệu người dùng đăng ký, ít nhất 300.000 request/giây.
  • Vấn đề: code rối (thư mục lib/model/controllers, không ai sở hữu chất lượng, thêm import cycle để kịp ra tính năng); deploy hằng ngày nhưng hàng trăm developer chung một bản nên gần như ngày nào cũng có bug nghiêm trọng, rollback cả monolith, lịch đẩy không đoán được; không rollout được thứ hạ tầng mới chỉ cho route ít quan trọng; framework HTTP cũ chỉ hỗ trợ HTTP/1.0, metric và tracing phải làm lại riêng.

Thay đổi chính

  • SOA thất bại một nửa: hơn một năm rưỡi mới xong mốc 1 (tách chức năng lõi ra RPC, quy trình production readiness); càng nhiều team và service vào đường đi của traffic khách, càng khó giữ độ tin cậy, nhất là khi bắt team sản phẩm tự vận hành service.
  • Phân loại lại: hệ lớn, phức tạp (chia sẻ file: trạng thái, quyền, quota) vẫn là service riêng do team lớn vận hành; phần lớn tính năng là nhỏ, tự đủ (trang chủ) và không cần service tự vận hành, vì sự cố của chúng có chung kiểu (spike từ ngoài, service phía dưới lỗi).
  • Atlas, nền tảng managed "giống serverless": developer chỉ viết interface và cài đặt endpoint; nền tảng tạo cluster, đẩy code, giám sát.
    • Atlasservlet: gom route theo tính năng (hơn 200 servlet cho hơn 5.000 route), mỗi cái một thư mục riêng do một chủ sở hữu, người khác không import được (Bazel visibility); phá import cycle mất nhiều năm với script và refactor, chặn tái phát bằng cùng cơ chế.
    • Mỗi servlet một cluster: cô lập lỗi mặc định, đẩy độc lập; cấu hình sinh tự động (dưới 50 dòng boilerplate); Envoy định tuyến theo route; giữa service dùng gRPC, HTTP qua gRPC-HTTP transcoding của Envoy; adapter chuyển endpoint cũ sang interface gRPC, chạy được ở cả Metaserver lẫn Atlas trong lúc chuyển.
    • Vận hành tự động: mỗi service có ba deployment canary/control/production; control khởi động lại bản cũ cùng lúc với canary để so công bằng (giống Kayenta), tự dừng và rollback; autoscaler giữ trên 40% headroom mỗi cluster theo độ dài hàng đợi request từ Envoy, vì nhiều cluster nhỏ mất khả năng hấp thụ spike của cluster chung lớn.
  • "Stepping stones, not milestones": mỗi bước có giá trị riêng nếu bước sau thất bại: tăng tốc test của Metaserver trước, cải thiện bộ nhớ cho Metaserver độc lập với Atlas, load test dùng lại cho dự án phần cứng, làm gRPC nội bộ trước phần rủi ro (transcoding).
  • Khó khăn: hành vi kỳ quặc của stack HTTP cũ (so output từng byte giữa hệ cũ và mới); không chạy nổi hơn 200 process Python trong test tích hợp nên gộp lại thành monolith khi dev và test; service hạ tầng hardcode danh tính Metaserver cho phân quyền.
  • Trạng thái 2021: Atlas phục vụ hơn 25% traffic cũ của Metaserver.

Vì sao

  • Theo bài, developer không quan tâm monolith hay service, chỉ muốn cách ít chi phí nhất để đưa giá trị tới khách; tách mù quáng thành service sẽ đẩy tải vận hành lên cả tổ chức.

Bài học cho SWE

  • Ranh giới code (thư mục có chủ, import bị chặn) là phần có hiệu quả chiến lược nhất: ngăn code mới làm vấn đề tệ thêm.
  • Tách deploy và cô lập lỗi theo tính năng không đòi team sản phẩm phải vận hành service; một nền tảng managed gánh việc đó với canary, autoscale, alert tự động.
  • Một hình dạng cho production (nhiều cluster), một hình dạng cho dev/test (gộp lại).

Liên quan