Menu
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Đang tải...

gRPC overview: high-performance RPC cho BA

API and Technical Fundamentals cho BA Bài 29/60

Mở đầu — vì sao bài này quan trọng

Hãy tưởng tượng bạn là BA của một sàn thương mại điện tử ở Việt Nam. Mỗi khi khách bấm "Đặt hàng", hệ thống phía sau phải làm hàng loạt việc: kiểm tra tồn kho, tính phí ship, trừ điểm tích lũy, gọi cổng thanh toán, gửi thông báo. Mỗi việc đó nằm ở một service riêng. Các service này nói chuyện với nhau hàng nghìn lần mỗi giây. Nếu cách "nói chuyện" đó chậm hoặc nặng, toàn hệ thống ì ạch theo.

Trong các bài trước bạn đã làm quen với REST API — chuẩn giao tiếp phổ biến nhất giữa client và server. REST tuyệt vời cho web, cho mobile, cho đối tác bên ngoài. Nhưng khi các service nội bộ cần gọi nhau với tốc độ cực cao và độ trễ cực thấp, nhiều công ty lớn chuyển sang một công nghệ khác: gRPC.

Là BA, bạn không cần tự viết gRPC. Nhưng bạn sẽ gặp nó trong tài liệu kiến trúc, trong các cuộc họp với team backend, trong quyết định "service này dùng REST hay gRPC?". Nếu bạn hiểu gRPC là gì, nó khác REST ra sao, và khi nào nên dùng, bạn sẽ viết spec chuẩn hơn, đặt câu hỏi đúng hơn, và được dev tôn trọng hơn. Đó chính là mục tiêu của bài này: cho bạn đủ chiều sâu để tham gia thảo luận một cách tự tin, mà không sa vào chi tiết lập trình.

Khái niệm cốt lõi

gRPC là gì?

gRPC viết tắt của google Remote Procedure Call — một framework do Google phát triển và mở mã nguồn năm 2015, nay thuộc tổ chức CNCF (cùng nhà với Kubernetes).

Ý tưởng cốt lõi nằm ở chữ RPC — Remote Procedure Call, tức "gọi thủ tục từ xa". Bạn hãy nhớ lại cách lập trình thông thường: khi viết code, bạn gọi một hàm như tinhPhiShip(diaChi, canNang) và nhận kết quả ngay. Hàm đó nằm cùng máy với bạn. RPC mở rộng ý tưởng này: bạn vẫn gọi một hàm như vậy, nhưng hàm đó thực ra nằm trên một máy chủ khác, ở một service khác, có khi ở một trung tâm dữ liệu khác. gRPC lo toàn bộ phần "đi qua mạng" giúp bạn, đến mức dev có cảm giác đang gọi một hàm local.

Tóm gọn bằng một câu: gRPC là cách để một chương trình gọi hàm của chương trình khác qua mạng, giống như gọi hàm trong cùng máy, nhưng nhanh và gọn hơn REST.

So sánh tư duy:

  • REST tư duy theo tài nguyên (resource): bạn thao tác trên GET /orders/123, POST /orders. Bạn nghĩ về danh từ.
  • gRPC tư duy theo hành động (action/method): bạn gọi GetOrder(id=123), CreateOrder(...). Bạn nghĩ về động từ, về hàm.

Hai trụ cột kỹ thuật: HTTP/2 và Protocol Buffers

gRPC nhanh nhờ hai nền tảng quan trọng. Là BA bạn nên nắm ý nghĩa của chúng.

Trụ cột 1 — HTTP/2. REST truyền thống chạy trên HTTP/1.1, nơi mỗi request thường chiếm một kết nối và phải xếp hàng chờ nhau. HTTP/2 cho phép multiplexing: nhiều request và response chạy song song trên cùng một kết nối, không kẹt cổ chai. Nó cũng nén header và hỗ trợ luồng dữ liệu hai chiều liên tục (streaming). Đây là lý do gRPC duy trì được độ trễ thấp khi gọi qua lại dồn dập.

Trụ cột 2 — Protocol Buffers (protobuf). Đây là điểm khác biệt lớn nhất so với REST. REST thường dùng JSON — định dạng văn bản, con người đọc được, nhưng nặng vì toàn chữ. gRPC dùng protobuf, một định dạng nhị phân (binary): dữ liệu được mã hóa thành byte gọn nhẹ mà máy đọc cực nhanh, con người thì không đọc trực tiếp được. Một message JSON 1.000 byte có thể chỉ còn 300–400 byte khi mã hóa bằng protobuf. Ít byte hơn nghĩa là truyền nhanh hơn, tốn ít băng thông hơn, parse nhanh hơn.

File .proto — "hợp đồng" mà BA cần quan tâm nhất

Trong gRPC, mọi thứ bắt đầu từ một file định nghĩa gọi là file .proto. Đây là phần BA nên đọc hiểu được, vì nó chính là bản hợp đồng (contract) mô tả service làm được gì.

Ví dụ một file .proto đơn giản cho service đơn hàng:

syntax = "proto3";

service OrderService { rpc GetOrder (GetOrderRequest) returns (Order); rpc CreateOrder (CreateOrderRequest) returns (Order); }

message GetOrderRequest { string order_id = 1; }

message Order { string order_id = 1; string customer_name = 2; int32 total_amount = 3; string status = 4; }

Đọc file này, ngay cả khi không phải dev, bạn cũng hiểu được:

  • Service tên OrderService cung cấp hai hàm: GetOrderCreateOrder.
  • GetOrder nhận vào một GetOrderRequest (chứa order_id) và trả về một Order.
  • Một Order gồm có mã đơn, tên khách, tổng tiền, trạng thái.
Những con số = 1, = 2số thứ tự trường (field number) — chúng định danh từng trường trong dữ liệu nhị phân và không bao giờ được đổi tùy tiện vì sẽ phá vỡ tương thích. Đây là chi tiết nhỏ nhưng quan trọng khi bạn review thay đổi spec.

Từ file .proto này, công cụ gRPC tự sinh ra code cho cả phía gọi (client) lẫn phía nhận (server), bằng nhiều ngôn ngữ khác nhau — Java, Go, Python, Node, C#... Đây là điểm mạnh: một hợp đồng, nhiều ngôn ngữ, luôn đồng bộ.

Bốn kiểu giao tiếp của gRPC

REST về cơ bản là "hỏi một câu, đáp một câu". gRPC linh hoạt hơn với bốn kiểu:

  • Unary — gọi một lần, trả về một lần. Giống REST nhất. Ví dụ GetOrder.
  • Server streaming — gọi một lần, server trả về một luồng nhiều message. Ví dụ "cho tôi xem tiến trình giao hàng theo thời gian thực".
  • Client streaming — client gửi một luồng nhiều message, server trả lời một lần. Ví dụ tải lên nhiều bản ghi cảm biến rồi nhận một bản tổng kết.
  • Bidirectional streaming — cả hai bên cùng gửi luồng đồng thời. Ví dụ chat hai chiều, hoặc theo dõi giá cổ phiếu liên tục.
Khả năng streaming này là lý do gRPC rất hợp với hệ thống real-time và truyền dữ liệu lớn.

Tình huống thực tế

Tình huống 1 — Sàn TMĐT "ShopViet" và bài toán độ trễ nội bộ

ShopViet (giả định) là một sàn TMĐT tại TP.HCM xử lý khoảng 5 triệu lượt gọi giữa các service mỗi giờ vào giờ cao điểm sale. Ban đầu mọi service nội bộ nói chuyện với nhau bằng REST/JSON. Khi lưu lượng tăng, team backend phát hiện riêng việc serialize/deserialize JSON đã ngốn đáng kể CPU, và mỗi đơn hàng phải đi qua 7–8 service khiến độ trễ cộng dồn lên tới 800ms.

Họ chuyển các cuộc gọi nội bộ giữa service với service sang gRPC, giữ nguyên REST cho API ra ngoài (mobile app, đối tác). Kết quả sau ba tháng: kích thước payload trung bình giảm khoảng 60%, độ trễ cộng dồn cho luồng đặt hàng giảm còn ~350ms, và CPU của cụm xử lý đơn hàng giảm đủ để bớt được vài máy chủ.

Bài học cho BA: gRPC tỏa sáng ở giao tiếp đông–nhanh–nội bộ (east-west traffic), nơi cả hai đầu đều do công ty kiểm soát. Khi viết tài liệu kiến trúc, hãy phân biệt rõ "API đối ngoại" và "giao tiếp nội bộ" — chúng có thể dùng hai công nghệ khác nhau, và điều đó hoàn toàn bình thường.

Tình huống 2 — Fintech "PayNhanh" và quyết định REST hay gRPC cho đối tác

PayNhanh (giả định), một công ty ví điện tử, có một service tính điểm tín dụng nội bộ mà nhóm chống gian lận gọi tới hàng nghìn lần mỗi giây. Họ chọn gRPC cho đường này — đúng đắn, vì nội bộ, tần suất cao.

Nhưng khi một ngân hàng đối tác muốn tích hợp để truy vấn điểm tín dụng, BA dự án ban đầu định ép đối tác dùng gRPC cho "đồng bộ". Trong buổi làm việc, phía ngân hàng cho biết hệ thống của họ chỉ quen REST/JSON, đội tích hợp không có kinh nghiệm protobuf, và họ muốn test bằng Postman quen thuộc. BA nhận ra việc bắt đối tác học gRPC sẽ kéo dài tích hợp thêm nhiều tuần.

Giải pháp: dựng một lớp API Gateway REST ở rìa hệ thống cho đối tác, bên trong gateway dịch sang gRPC để gọi service nội bộ. Đối tác chỉ thấy REST quen thuộc; lợi ích tốc độ của gRPC vẫn được giữ ở bên trong.

Bài học cho BA: Đối tượng tiêu thụ API quyết định công nghệ. Với bên ngoài, sự phổ biến và dễ tích hợp của REST thường thắng. Đừng chọn công nghệ vì nó "ngầu" hay vì "cho đồng bộ" — hãy chọn theo người dùng thực tế. Câu hỏi vàng BA nên đặt: "Ai sẽ gọi API này, và họ quen với gì?"

Tình huống 3 — Ứng dụng gọi xe và dữ liệu vị trí real-time

Một ứng dụng gọi xe ở Đông Nam Á cần cập nhật vị trí tài xế liên tục về phía hành khách và trung tâm điều phối — nhiều lần mỗi giây, cho hàng trăm nghìn xe. Dùng REST kiểu hỏi-đáp (polling) sẽ tạo ra lượng request khổng lồ và lãng phí. Team chọn gRPC bidirectional streaming: app tài xế và server giữ một luồng mở, đẩy tọa độ liên tục theo cả hai chiều, độ trễ rất thấp.

Bài học cho BA: Khi yêu cầu nghiệp vụ có chữ "real-time", "liên tục", "đẩy dữ liệu", hãy ghi nhận đó là tín hiệu xem xét streaming. gRPC streaming là một lựa chọn mạnh cho lớp này (bài về WebSocket ở phần sau sẽ bàn một hướng khác cho trình duyệt web). Việc của bạn là mô tả đúng yêu cầu real-time trong spec để team kỹ thuật chọn công cụ phù hợp.

Hướng dẫn từng bước

Đây là cách một BA tiếp cận khi gặp gRPC trong dự án:

Bước 1 — Xác định đây có phải bối cảnh hợp với gRPC không. Hỏi ba câu: Giao tiếp này là nội bộ hay đối ngoại? Tần suất gọi cao hay thấp? Có yêu cầu độ trễ thấp / streaming không? Nội bộ + tần suất cao + cần nhanh → gRPC là ứng viên sáng giá. Đối ngoại + nhiều đối tác lạ → nghiêng về REST.

Bước 2 — Yêu cầu được xem file .proto. Đây là tài liệu hợp đồng. Đọc danh sách service, các rpc, và các message. Bạn không cần hiểu code, chỉ cần nắm: service cung cấp hành động gì, mỗi hành động cần input gì và trả ra gì.

Bước 3 — Map yêu cầu nghiệp vụ vào các method. Với mỗi nghiệp vụ ("xem chi tiết đơn", "tạo đơn", "hủy đơn"), kiểm tra xem đã có rpc tương ứng chưa, input/output đã đủ trường chưa. Thiếu trường nào, ghi rõ trong spec để dev bổ sung vào .proto.

Bước 4 — Làm rõ kiểu giao tiếp. Với mỗi method, xác nhận đó là unary hay streaming. Nếu nghiệp vụ là real-time/đẩy liên tục, ghi chú cần streaming và mô tả luồng dữ liệu mong đợi.

Bước 5 — Thống nhất quy tắc thay đổi hợp đồng. Cùng team đặt quy tắc: không đổi/không tái sử dụng số thứ tự trường cũ, chỉ thêm trường mới với số mới; method cũ giữ nguyên, thêm method mới khi cần. Đây là nền tảng cho khả năng tương thích ngược (bài về API versioning đã chạm tới tinh thần này).

Bước 6 — Thống nhất cách test và quan sát. Vì gRPC không test bằng trình duyệt như REST, hãy hỏi team dùng công cụ gì (ví dụ grpcurl, hoặc Postman bản mới đã hỗ trợ gRPC) để bạn cũng kiểm thử hành vi được. Đồng thời làm rõ cách báo lỗi: gRPC dùng bộ status code riêng (như NOT_FOUND, INVALID_ARGUMENT, UNAUTHENTICATED) thay cho mã HTTP 404/400/401 quen thuộc.

Lỗi thường gặp & mẹo

Lỗi 1 — Tưởng gRPC sẽ thay thế REST hoàn toàn. Không. Chúng bổ trợ nhau. Đa số kiến trúc trưởng thành dùng REST ở rìa (cho mobile, web, đối tác) và gRPC ở lõi (giữa service nội bộ). BA nói "ta bỏ REST chuyển hết sang gRPC" thường là dấu hiệu hiểu sai.

Lỗi 2 — Quên rằng trình duyệt không gọi gRPC trực tiếp được. Trình duyệt không hỗ trợ gRPC thuần; cần một biến thể gọi là gRPC-Web kèm proxy. Vì vậy đừng vẽ sơ đồ "web app gọi thẳng gRPC service" mà không có lớp trung gian.

Lỗi 3 — Coi nhẹ chi phí học và công cụ. protobuf nhị phân không đọc bằng mắt như JSON, debug khó hơn, đội ngũ cần học. Với team nhỏ, dự án nhỏ, lưu lượng thấp, REST/JSON đơn giản thường là lựa chọn khôn ngoan hơn. Đừng "dùng gRPC cho oai".

Lỗi 4 — Tùy tiện đổi field number trong .proto. Đây là lỗi kỹ thuật nhưng BA cần cảnh giác khi review thay đổi spec: đổi số thứ tự trường hoặc tái dùng số cũ sẽ làm dữ liệu cũ bị diễn giải sai, gây bug khó lần.

Mẹo 1 — Học một câu để giải thích cho stakeholder: "gRPC giống như gọi điện nội bộ giữa các phòng ban bằng số máy lẻ — nhanh, gọn, nhưng chỉ dùng trong công ty; còn REST giống như gọi tổng đài công khai cho khách bên ngoài."

Mẹo 2 — Khi đứng giữa REST và gRPC, hãy quyết theo người tiêu thụ trước, hiệu năng sau. Người dùng lạ, đa dạng → REST. Người dùng nội bộ, cần nhanh → cân nhắc gRPC.

Mẹo 3 — Lưu sẵn file .proto vào tài liệu dự án như một tạo tác (artifact) quan trọng. Nó vừa là spec, vừa là tài liệu kỹ thuật, vừa là điểm tham chiếu khi nghiệm thu.

Bài tập thực hành

  • Đọc hợp đồng: Quay lại file .proto mẫu trong bài. Hãy viết bằng lời (tiếng Việt) mô tả service OrderService làm được gì, mỗi method nhận và trả về thông tin gì — như thể bạn đang giải thích cho một stakeholder phi kỹ thuật.
  • Quyết định công nghệ: Cho ba tình huống sau, chọn REST hay gRPC và giải thích trong 2–3 câu: (a) API cho phép hàng trăm shop đối tác đẩy sản phẩm lên sàn; (b) service kiểm tra tồn kho được service giỏ hàng gọi 3.000 lần/giây trong nội bộ; (c) tính năng theo dõi vị trí shipper real-time trên app khách hàng.
  • Thiết kế method: Cho nghiệp vụ "khách hủy đơn hàng và nhận lại điểm tích lũy". Hãy phác một rpc (tên hàm, input cần trường gì, output trả về gì) theo phong cách .proto. Không cần đúng cú pháp tuyệt đối, quan trọng là tư duy đầy đủ input/output.
  • Đặt câu hỏi cho dev: Viết 5 câu hỏi bạn sẽ hỏi team backend trong buổi review một service gRPC mới, dựa trên 6 bước ở phần "Hướng dẫn từng bước".

Tóm tắt

  • gRPC là framework gọi hàm từ xa của Google, chạy trên HTTP/2 và dùng Protocol Buffers (protobuf) — định dạng nhị phân gọn, nhanh hơn JSON nhiều.
  • Khác REST (tư duy theo tài nguyên/danh từ), gRPC tư duy theo hành động/động từ — bạn gọi method như gọi hàm.
  • Trái tim của gRPC là file .proto — bản hợp đồng mô tả service có những method nào, input/output ra sao. Đây là tài liệu BA cần đọc hiểu được.
  • gRPC hỗ trợ bốn kiểu giao tiếp: unary, server streaming, client streaming, bidirectional streaming — rất mạnh cho real-time.
  • Điểm ngọt của gRPC: giao tiếp nội bộ, tần suất cao, cần độ trễ thấp. Với API đối ngoại nhiều đối tác, REST thường thắng nhờ phổ biến và dễ tích hợp. Hai công nghệ bổ trợ chứ không thay thế nhau.
  • Câu hỏi vàng của BA: "Ai gọi API này, tần suất bao nhiêu, có cần real-time không?" — câu trả lời sẽ dẫn bạn tới lựa chọn đúng.