Ready for changes with Hexagonal Architecture

Bài tóm tắt Netflix 2020 4. Điều chỉnh Độ khó: Dễ

Netflix · 2020 · 4. Điều chỉnh · Độ khó: Dễ — bài gốc

Bài về kiến trúc bên trong một ứng dụng (Studio Engineering), không phải hạ tầng streaming. Wiki giữ vì nó kể cách một app mới sống cạnh một monolith đang bị tách dần.

Bối cảnh

  • Studio Engineering của Netflix có nhiều app phục vụ sản xuất phim (mua kịch bản, đàm phán, lịch quay...). Một app đời đầu là monolith: phát triển nhanh khi chưa ai hiểu miền nghiệp vụ; có lúc hơn 30 developer và hơn 300 bảng.
  • Monolith được quyết định tách thành service, không phải vì hiệu năng mà để vạch ranh giới giữa các miền và cho các team làm độc lập.
  • Khoảng 2019, team Studio Workflows làm một app mới cần dữ liệu từ nhiều hệ (gRPC, JSON API, GraphQL). Phần lớn dữ liệu vẫn nằm ở monolith, và chắc chắn sẽ dời sang service mới nhưng không biết khi nào.

Thay đổi chính

  • Dựng app theo kiến trúc lục giác (ports and adapters): logic nghiệp vụ ở giữa, không biết dữ liệu đến từ DB, gRPC, REST hay file CSV, cũng không biết được gọi qua REST hay GraphQL.
  • Ba khái niệm lõi: Entity (đối tượng miền, không biết mình được lưu ở đâu, khác Active Record), Repository (interface lấy và sửa entity), Interactor (thực hiện một hành động nghiệp vụ). Bên ngoài: Data Source (adapter cài đặt repository cho từng kho) và Transport Layer (API, event, cron, CLI đều gọi được interactor). Mọi phụ thuộc hướng vào trong.
  • Đổi nguồn dữ liệu thật: sớm hơn dự kiến, app chạm giới hạn đọc của monolith và phải chuyển việc đọc một entity sang service mới qua lớp GraphQL (hai bên đã được đồng bộ dữ liệu). Viết một data source GraphQL cài đặt repository có sẵn, rồi đổi một dòng: chuyển xong trong 2 giờ. Nguồn được chọn qua cấu hình, nên tách được deploy khỏi bật, rollback dễ.
  • Che chi tiết nguồn: service phía dưới chưa có API lấy nhiều bản ghi; repository vẫn khai báo hàm lấy nhiều, bản đầu gọi song song nhiều request đơn, sau thay bằng API bulk mà không đụng logic.
  • Test ba tầng: interactor (nhiều nhất, mock repository), data source (ít, kiểm tra tích hợp và cách xử lý lỗi), integration (một ca thành công, một ca lỗi cho mỗi hành động; ghi lại response của API ngoài vào git). Khoảng 3.000 spec chạy trong 100 giây trên một process.

Vì sao

  • Theo Netflix, đầu dự án là lúc biết ít nhất; kiến trúc này cho phép hoãn quyết định (lưu dữ liệu ở đâu, kho quan hệ hay document) tới khi biết nhiều hơn.

Bài học cho SWE

  • Khi monolith đang bị tách, app phụ thuộc vào nó nên đặt ranh giới (repository) ở phía mình, để việc dời nguồn dữ liệu chỉ là đổi adapter (Monolith và microservices — đi và quay lại).
  • Đổi nguồn qua cấu hình, có hai nguồn cùng dữ liệu chạy song song, là dạng nhỏ của migrate không downtime: tách deploy khỏi kích hoạt, rollback bằng một dòng (Migration không downtime).
  • Lý do tách monolith ở đây là ranh giới tổ chức, không phải tải; cùng kết luận với nhiều nguồn khác trong concept.
  • Ranh giới rõ cho bộ test nhanh, không phụ thuộc giao thức hay đổi.

Liên quan