Cơ bản về gRPC và cách Protobuf mã hóa giữ liệu trong gRPC

  • Published onJanuary 20, 2023

Nếu bạn đang phân vân lựa chọn những cách giao tiếp giữa client/server hoặc những service với nhau trong một hệ thống microservice, thì có thể bạn đã nghe qua về gRPC qua các bài viết khác trên Internet. Bài viết này sẽ không hướng dẫn về cách thực hiện về coding, mà tập trung vào giải thích cách protobuf mã hóa dữ liệu trong gRPC.

gRPC là gì?

gRPC là framework mã nguồn mở để thực hiện các giao thức RPC với hiệu năng cao và có thể chạy trên mọi môi trường. Nó cho phép các máy chủ và máy khách giao tiếp với nhau một cách minh bạch và đơn giản hóa bằng việc xây dựng các hệ thống.

Những ưu điểm của gRPC:

  • Giảm lượng dữ liệu truyền đi qua lại giữa client/server để làm giảm băng thông, tăng tốc độ nhận truyền.
  • Hỗ trợ nhiều ngôn ngữ lập trình.
  • Hỗ trợ nhiều dạng kết nối: Server streaming RPC, client streaming RPC, Bidirectional streaming RPC, Unary RPC.
  • gRPC được phát triển bởi Google nên việc phát triển, hỗ trợ, bảo trì được đảm bảo.

So sách nhỏ giữa REST và gRPC:

Tính năng gRPC REST
Giao thức HTTP/2 HTTP/1.1
Dữ liệu truyền Protobuf (dạng binary, được tối ưu) JSON(dạng text)
Kiểu dữ liệu Ràng buộc, yêu cầu Lỏng lẻo, tùy ý

Vì sao kích thước dữ liệu truyền được giảm khi sử dụng gRPC?

Ví dụ khi cần truyền dữ liệu mô tả công ty theo dạng JSON. Ta có thể dễ dàng viết như thế này:

{
	"id": 23,
	"company_name": "PIXTA VIETNAM",
	"members_size": 50,
	"products": ["Pixta stock", "Pixta AI", "xFrame"]
}

Khi JSON được mã hóa về dạng có thể truyền qua Internet, nếu được xóa bỏ các khoảng trắng, đoạn JSON trên sẽ tiêu tốn 102 bytes.

Bây giờ, ta sẽ sử dụng protobuf để mã hóa cùng kiểu dữ liệu cần truyền trên. Như đã nói ở đầu bài viết, khi sử dụng gRPC, ta cần định nghĩa kiểu dữ liệu vào/ra cho cả client/server. Ở ví dụ dưới, ta định nghĩa cho thông tin cơ bản cho một công ty trong file có phần mở rộng .proto

message Company {
	required int64   id               = 1
	required string  company_name     = 2
	required int64   members_size     = 3
	repeated string  products         = 4
}

Khi chúng ta mã hóa dữ liệu công ty trên với schema đã được định.

draw.drawio (1).png

Sau khi mã hóa, dữ liệu sau khi mã hóa chỉ chiếm 50 bytes ⇒ bằng một nửa so với sử dụng JSON.

Ta có thể dễ dàng thấy, nếu sử dụng dạng JSON, dữ liệu nhị phân được truyền đi sẽ bao gồm cả tên trường dữ liệu (id, company_name, member_sizes, products). Nó sẽ tốn tương đối đáng kể băng thông khi truyền qua Internet. Trong khi đó, nếu sử dụng protobuf dữ liệu nhị phân cần truyền chỉ là một chuỗi giá trị không kèm theo tên trường. Việc giải mã sẽ được phía client dễ dàng thực hiện bằng việc sử dụng định nghĩa kiểu giá trị từ trước theo tuần tự trường thông tin (field tag) 1, 2, 3 mà không cần phải sử dụng cụ thể như với JSON.

Tuy nhiên với những ưu điểm trên, gRPC còn có những điểm yếu cần xem xét khi sử dụng.

Một số lưu ý khi sử dụng

  • gRPC sử dụng HTTP 2 thay vì HTTP 1.1 vì vậy sẽ có các hạn chế như: hỗ trợ các trình duyệt, việc deploy các services trong hệ thống cần sử dụng service registry khi có thêm service như load balancer, …
  • Việc dùng Protocol Buffers để mã hóa dữ liệu dẫn đến dữ liệu được truyền qua các service khó để đọc được một cách bình thường thay vì dùng JSON hay XML
  • Vì cơ chế gRPC cần định nghĩa dữ liệu ra/vào ở cả hai phía client và server nên quá trình phát triển cần đồng bộ các file liên quan đến gRPC và protobuf.

Vậy với những ràng buộc đôi chút phức tạp trên vì sao những hệ thống lớn đặc biệt là các hệ thống sử dụng kiến trúc microservice được ưu tiên sử dụng? Tất nhiên khi chọn những công cụ để sử dụng trong hệ thống chúng ta cần phải xem xét về đánh đổi trade off giữa các công cụ/công nghệ.

Kết luận

Việc sử dụng gRPC mục đích chính là giúp hệ thống tối ưu về băng thông cũng như tốc độ khi truyền thông tin qua lại giữa client/server. Nhưng thực tế khi sử dụng cần phải xem xét đánh đổi giữa nhiều yếu tố, ví dụ: giao thức HTTP 2 hay HTTP1.1, việc coding khi sử dụng gRPC sẽ cần khó khăn hơn khi dùng dạng truyền thống như JSON, loại dữ liệu truyền/ nhận giữa client/server,…

Tham khảo

  1. Martin Kleppmann – Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems 1st Edition[117-121].
  2. https://grpc.io/docs/what-is-grpc/core-concepts/
  3. https://developers.google.com/protocol-buffers/docs/overview
  4. https://microservices.io/patterns/service-registry.html

Tác giả: Bùi Xuân Ngọc

Tìm hiểu thêm về cơ hội làm việc tại Pixta Vietnam

🌐 Website: https://pixta.vn/careers

🏠 Facebook: https://www.facebook.com/pixtaVN

🔖 LinkedIn: https://www.linkedin.com/company/pixta-vietnam/

✉️ Email: recruit.vn@pixta.co.jp

☎️ Hotline: 024.6664.1988

Latest Post