0

[Series System Design - Bài 6] API Gateway & BFF (Backend for Frontend): Quản lý luồng giao tiếp chằng chịt giữa Client và các Services

Chào anh em. Ở bài trước, chúng ta đã chia thành công khối Monolith khổng lồ thành 20 cái Microservices nhỏ xinh. Backend dev nhìn nhau cười đắc ý vì giờ đây ai code phần người nấy, deploy không đụng chạm nhau.

Nhưng nụ cười ấy chợt tắt khi team Frontend và Mobile app bước vào phòng họp.

Để hiển thị trang chi tiết sản phẩm của một hệ thống bán lẻ mỹ phẩm, app Mobile phải gọi 1 request lên Product-Service lấy thông tin cơ bản, 1 request lên Inventory-Service check tồn kho, 1 request lên Promotion-Service xem có mã giảm giá nào không, và 1 request lên Review-Service lấy đánh giá. Tổng cộng: 4 vòng request (round-trips) từ điện thoại của người dùng lên server.

Trải nghiệm trên app bỗng trở nên rùa bò, pin điện thoại sụt nhanh hơn tụt huyết áp vì phải giữ kết nối mạng liên tục. Hơn nữa, việc phơi bày cả 20 cái IP/Domain của 20 services ra ngoài internet là một thảm họa về bảo mật.

Đó là lúc chúng ta phải triệu hồi hai "vị thần gác cửa": API GatewayBFF (Backend for Frontend).

1. API Gateway: Lễ tân tối cao của tòa nhà

Hãy tưởng tượng dàn Microservices của bạn là một tòa nhà văn phòng có 20 công ty bên trong. Bạn không thể để khách hàng tự do đi thang máy, mò mẫm gõ cửa từng công ty được. Bạn cần một Quầy Lễ Tân (API Gateway).

API Gateway là một server đứng duy nhất ở cổng vào. Mọi request từ thế giới bên ngoài (Web, Mobile, Đối tác thứ 3) ĐỀU PHẢI đi qua nó trước khi lọt vào các services bên trong.

Quyền năng của API Gateway:

  • Routing (Điều hướng): Khách gọi /api/orders, Gateway sẽ tự động định tuyến nó tới Order-Service (chạy ở IP 10.0.0.5:8080). Client hoàn toàn mù tịt về kiến trúc mạng bên trong của bạn.
  • Authentication & Authorization (Xác thực & Phân quyền): Thay vì service nào cũng phải viết lại code check token JWT, Gateway sẽ đứng ra xét giấy tờ. Token hợp lệ mới cho qua. Cực kỳ an toàn và DRY (Don't Repeat Yourself).
  • Rate Limiting (Giới hạn lưu lượng): Một gã hacker đang cố tình brute-force hoặc ddos hệ thống? Gateway sẽ chặn đứng request của hắn ngay tại cửa nếu vượt quá 100 request/phút. Các services bên trong vẫn bình yên vô sự.
  • SSL Termination: Mọi chứng chỉ bảo mật HTTPS đều xử lý ở Gateway, bên trong nội bộ các services chỉ cần nói chuyện với nhau bằng HTTP cho nhanh.

Các công cụ phổ biến: Kong, NGINX, AWS API Gateway, hoặc Spring Cloud Gateway.

2. Sự bế tắc của API Gateway và sự ra đời của BFF

Dùng API Gateway một thời gian, bạn lại nhận ra một nỗi đau khác: Over-fetching (Lấy thừa data)Under-fetching (Lấy thiếu data).

Màn hình Web (Desktop) có không gian rộng, cần hiển thị 20 trường thông tin (tên, giá, mô tả dài, 10 cái ảnh HQ, đánh giá chi tiết). Nhưng màn hình Mobile app thì bé xíu, nó chỉ cần 5 trường (tên, giá, thumbnail, rating sao).

Nếu API Gateway trả về một cục JSON khổng lồ cho cả hai, Mobile sẽ bị ngốn băng thông vô ích (3G/4G kéo cục data 1MB chỉ để hiển thị 50KB). Nếu cắt xén JSON cho vừa Mobile, thì Web lại không đủ data để hiển thị. Vậy chẳng lẽ trong Gateway ta lại phải viết hàng tá lệnh if (client == 'mobile')?

Để giải quyết mớ bòng bong này, Sam Newman (tác giả cuốn Building Microservices) đã phổ biến một pattern: BFF - Backend for Frontend.

3. BFF: May đo riêng cho từng nền tảng

Ý tưởng của BFF rất đơn giản: Mỗi một loại Client (Web, Mobile iOS, Mobile Android, Smartwatch) sẽ có một API Gateway "mini" của riêng nó, gọi là BFF.

  • BFF cho Mobile: Nhận request từ App Mobile, tự đứng ra gọi song song (aggregate) 4 services bên trong, nhào nặn data, vứt hết các trường thừa thãi, đóng gói thành một cục JSON nhỏ gọn nhất rồi trả về cho Mobile. App Mobile chỉ cần gọi ĐÚNG 1 request.
  • BFF cho Web: Tương tự, nhưng nó sẽ gọi thêm nhiều services khác và trả về cục JSON đầy đủ chi tiết để Web tha hồ vẽ vời UI.

Đặc điểm sống còn của BFF: BFF sinh ra là để phục vụ Frontend. Do đó, team viết BFF thường chính là team Frontend/Mobile hoặc team Fullstack phụ trách cái app đó. Backend dev (người viết Core Services) không cần quan tâm UI hiển thị gì, họ chỉ cung cấp raw data. Team UI tự viết BFF để "xào nấu" data theo ý mình. Điều này giúp các team giải phóng sự phụ thuộc lẫn nhau (Decoupling) và đẩy nhanh tốc độ release tính năng.

Lời kết

Trong hệ thống phân tán, API Gateway giải quyết bài toán về "Kiểm soát và Bảo mật hạ tầng", còn BFF giải quyết bài toán về "Trải nghiệm người dùng và Tối ưu băng thông". Không có đúng hay sai tuyệt đối, một hệ thống lớn hoàn toàn có thể dùng một API Gateway khổng lồ ở ngoài cùng, và đằng sau nó là các BFF cho từng nền tảng.

Tuy nhiên, giao tiếp có mượt mà đến đâu, code có clean đến đâu, thì dữ liệu cuối cùng cũng phải nằm lại ở một nơi nào đó. Và khi nhắc đến chỗ lưu trữ dữ liệu, chúng ta lại đụng độ một cuộc chiến đẫm máu không kém cuộc chiến Monolith - Microservices.

👉 Đó là lúc chúng ta bước sang bài tiếp theo: "Relational vs. NoSQL: Đừng chọn Database theo trend. Phân tích bài toán để chọn đúng công cụ (MySQL/PostgreSQL vs MongoDB/Cassandra)."

Anh em đã từng vật vã cấu hình NGINX làm Gateway, hay từng phải hì hục viết một layer trung gian để "gọt" data cho app Mobile chưa? Thả bình luận chia sẻ kinh nghiệm nhé! Nhớ follow để không bỏ lỡ trận chiến Database ở bài sau!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí