← Series hub Next →

Bài 1: Xây dựng nền tảng khổng lồ với Microservices, Golang và gRPC

Trong phần đầu tiên của series phân tích kiến trúc Shopee, chúng ta sẽ đi sâu vào “móng nhà” của họ. Để phục vụ hàng triệu người dùng cùng lúc (high-concurrency), kiến trúc nguyên khối (Monolithic) là bất khả thi vì chỉ cần một chức năng quá tải sẽ kéo sập cả hệ thống. Giải pháp bắt buộc là Kiến trúc Microservices.

1. Tại sao Shopee lại chọn Golang?

Mặc dù Java là ngôn ngữ truyền thống trong các hệ thống Enterprise, Shopee đã quyết định chọn Golang (Go) cho phần lớn hệ thống core backend của mình.

  • Goroutines & Xử lý đồng thời (Concurrency) tuyệt đỉnh: Trong Java/C++, mỗi thread gắn với một OS Thread, tiêu tốn khoảng 1-2MB RAM. Với Go, các Goroutines chạy trên User Space và được Go Runtime tự động điều phối (M:N scheduling) vào các OS Threads. Một Goroutine chỉ tốn khoảng 2KB RAM. Nhờ đó, một instance backend nhỏ gọn của Shopee có thể xử lý hàng chục nghìn kết nối đồng thời (10k+ C10K problem) mà không bị cạn kiệt tài nguyên bộ nhớ.
  • Hiệu năng biên dịch trực tiếp (Compiled Language): Go biên dịch thẳng ra mã máy (Machine Code). Không có độ trễ khởi động hay JIT overhead như Java JVM. Khởi động cực nhanh, rất hoàn hảo cho môi trường Kubernetes khi cần scale-up hàng trăm Pods trong vài giây.

2. Giao tiếp nội bộ (Inter-Service): Sức mạnh của gRPC

Bên trong “vương quốc” Shopee có hàng ngàn Microservices. Nếu chúng gọi nhau bằng RESTful API (HTTP/1.1 + JSON), hệ thống sẽ bị chậm đi rất nhiều do overhead của việc parse chữ (text). Giải pháp thay thế là gRPC.

  • Sử dụng HTTP/2: gRPC chạy trên nền HTTP/2, cho phép Multiplexing (Gửi nhiều request đồng thời qua một kết nối TCP duy nhất) và hỗ trợ Streaming hai chiều. Giúp loại bỏ hiện tượng thắt cổ chai Head-of-Line blocking.
  • Protocol Buffers (Protobuf): Thay vì gửi chuỗi JSON tốn dung lượng, gRPC serialize dữ liệu thành dạng nhị phân (Binary). Kích thước payload giảm đi một nửa, và tốc độ parse nhị phân nhanh hơn JSON hàng chục lần. Ngoài ra, việc dùng file .proto đóng vai trò như một “hợp đồng API” chặt chẽ, loại bỏ hoàn toàn các lỗi sai kiểu dữ liệu giữa các team.

3. Điều phối Traffic với API Gateway & Service Mesh

Khi người dùng mở app Shopee, điện thoại không bao giờ gọi trực tiếp vào Database hay Order Service. Mọi kết nối phải qua người gác cổng.

  • API Gateway (North-South Traffic): Nằm ở rìa mạng, đón traffic từ ngoài vào. Gateway đảm nhiệm các chức năng Cross-cutting như:
    • Xác thực (Auth / JWT Validation)
    • Rate Limiting (Giới hạn tốc độ): Sử dụng các thuật toán như Token Bucket hoặc Leaky Bucket. Nếu hệ thống phát hiện IP/Thiết bị spam 1000 requests/s, Gateway sẽ drop request đó ngay lập tức với mã 429 Too Many Requests, bảo vệ hoàn toàn backend phía sau.
  • Service Mesh (East-West Traffic): Bên trong hệ thống, Shopee áp dụng mô hình Service Mesh (ví dụ như Envoy/Istio). Các service không cần phải tự lo việc tìm địa chỉ IP của service khác (Service Discovery), hay việc thử lại khi gọi lỗi (Retry/Timeout). Một “Sidecar Proxy” chạy song song với mỗi service sẽ tự động gánh vác việc đó, tách biệt hoàn toàn logic hạ tầng khỏi logic nghiệp vụ (Business logic).
graph TD
    User([App / Web Shopee]) -->|HTTPS| API_Gateway[API Gateway<br/>Rate Limiting, Auth, Routing]
    
    subgraph "Shopee Core Backend (Golang + Service Mesh)"
        API_Gateway -->|gRPC| OrderService[Order Service]
        API_Gateway -->|gRPC| CatalogService[Catalog Service]
        OrderService -.->|gRPC| InventoryService[Inventory Service]
        OrderService -.->|gRPC| PaymentService[Payment Service]
    end
    
    InventoryService -.-> DB[(TiDB / MySQL)]

Bài học thực tiễn cho Dev: Xây nhà cao tầng phải có móng vững. Sự kết hợp giữa Microservices + Go + gRPC + API Gateway chính là bộ khung xương lý tưởng nhất hiện nay để xây dựng một hệ thống phân tán, chịu tải khổng lồ và độ trễ siêu thấp.