Service-Oriented Architecture: Scaling the Uber Engineering Codebase As We Grow

Bài tóm tắt Uber 2015 2. Tăng trưởng Độ khó: Dễ

Uber · 2015 · 2. Tăng trưởng · Độ khó: Dễ — bài gốc

Bối cảnh

  • Uber bắt đầu bằng một monolith cho một sản phẩm (UberBLACK) ở một thành phố (San Francisco). Lúc đầu để mọi logic một chỗ là hợp lý.
  • Khi mở thêm thành phố và sản phẩm:
    • Component dính chặt vào nhau; continuous integration thành gánh nặng vì deploy là deploy tất cả.
    • Số developer tăng nhanh: thêm tính năng, sửa bug, trả nợ kỹ thuật trên một repo cực khó; muốn sửa gì cũng cần "kiến thức truyền miệng".

Thay đổi chính

  • Tách monolith thành microservices, theo Amazon, Netflix, SoundCloud, Twitter. Mỗi service một domain hẹp, tự chọn ngôn ngữ và DB. Tháng 9/2015 đã có hơn 500 service; mục tiêu là bỏ hẳn repo monolith trong năm 2015.
  • Vấn đề mới, gói trong ba chữ:
    1. Obviousness: khó tìm service phù hợp; mỗi service một kiểu; contract REST/RPC lỏng lẻo và khác nhau. Một kỹ sư tóm lại: họ đã "biến API monolith thành API monolith phân tán".
    2. Safety: không có contract chặt thì không deploy độc lập được.
    3. Resilience: không có cách chuẩn xử lý timeout/sự cố phía client, dễ gây sự cố dây chuyền.
  • Giải pháp đang triển khai:
    • Apache Thrift làm IDL: định nghĩa kiểu và interface một chỗ, sinh code cho Python, Node, Go.
    • Công cụ phát hành client lên pip/npm.
    • Thư viện chịu lỗi lấy cảm hứng từ Hystrix (Netflix) và Finagle (Twitter).

Vì sao

Theo Uber: lý do chính là quy mô tổ chức (nhiều developer, deploy chung), cùng với quy mô traffic. Mục tiêu nêu rõ: quyền sở hữu rõ ràng, tổ chức scale được, chịu lỗi tốt hơn.

Bài học cho SWE

  • Tách service mà không có contract chặt và thư viện RPC chung thì chỉ thu được một monolith phân tán.
  • Đánh đổi chính Uber nêu: công cụ Thrift cho Python/Node còn non; không có header cấp cao nên xác thực và tracing xuyên service khó.
  • Đây là điểm khởi đầu. 5 năm sau, với ~2.200 service, Uber phải gom lại theo domain: Uber 2020.

Liên quan