Giới thiệu về Protocol Buffers

Xin chào các bạn 👋👋👋, trong bài viết này, chúng ta sẽ tìm hiểu về Protocol Buffers (Protobuf), một khái niệm mình đã đề cập trong bài viết giới thiệu về RPC và gRPC. Trong bài viết trước, mình chỉ giới thiệu sơ qua về Protobuf, vì vậy trong bài viết này, mình sẽ trình bày chi tiết hơn về Protobuf và giúp các bạn hiểu rõ hơn về cách sử dụng nó trong thực tế. Nếu bạn quan tâm đến bài viết trước về RPC và gRPC, bạn có thể tham khảo ở đây. Bây giờ, hãy bắt đầu thôi!!!

unnamed-1.png

Khái niệm

Protocol Buffers là một ngôn ngữ dùng để mô tả cấu trúc dữ liệu, tương tự như JSON hoặc XML, nhưng Protobuf lưu trữ dữ liệu có cấu trúc dưới dạng nhị phân một cách hiệu quả hơn, nhỏ gọn hơn và cho phép truyền dữ liệu nhanh hơn qua kết nối mạng. Protobuf được phát triển bởi Google và được công bố chính thức vào năm 2008.

Protobuf hỗ trợ hầu hết các loại ngôn ngữ lập trình hiện tại và không phụ thuộc vào bất kỳ nền tảng nào. Chúng ta có thể định nghĩa dữ liệu có cấu trúc một lần (với file .proto) và sử dụng cho các nền tảng khác nhau, tạo ra mã nguồn cho các ngôn ngữ khác nhau. Protobuf cung cấp một giải pháp hiệu quả để tạo dữ liệu có cấu trúc cho các ứng dụng khác nhau, chẳng hạn như ứng dụng web, hệ thống gRPC, và đặc biệt là hiệu quả trong việc triển khai microservices sử dụng gRPC.

Vấn đề mà protocol buffer giải quyết?

Protocol buffer hỗ trợ định dạng các gói dữ liệu có cấu trúc, có thể lên tới vài megabytes. Cấu trúc của nó phù hợp cho việc truyền dữ liệu qua mạng và lưu trữ dữ liệu lâu dài. Protobuf cũng cho phép mở rộng dữ liệu mới mà không ảnh hưởng đến các dữ liệu hiện có hoặc những dữ liệu cần được cập nhật. So với định dạng XML hoặc JSON, dữ liệu của Protobuf nhỏ gọn gấp 3-10 lần và được xử lý nhanh chóng. Bạn có thể tham khảo biểu đồ so sánh giữa Protobuf và JSON và XML khi sử dụng trong ngôn ngữ Go dưới đây.

Protobuf là giao thức định dạng dữ liệu phổ biến nhất tại Google. Nó được sử dụng rộng rãi để giao tiếp giữa các máy chủ và lưu trữ dữ liệu trên ổ đĩa. Protocol buffer message và services được định nghĩa bằng file .proto. Dưới đây là một ví dụ về message:

Có Thể Bạn Quan Tâm :   ” Quá Trình Sản Xuất Tiếng Anh Là Gì, Quá Trình Sản Xuất Tiếng Anh Là Gì

message Person {
optional string name = 1;
optional int32 age = 2;
optional string phone = 3;
}

Lợi ích

Protocol buffer là một ý tưởng tuyệt vời có thể áp dụng vào bất kỳ tình huống nào mà ta muốn tuần tự hoá dữ liệu có cấu trúc. Hiện nay, nó thường được sử dụng để định nghĩa giao tiếp dữ liệu qua mạng (cùng với gRPC) và để lưu trữ dữ liệu.

Một số ưu điểm của Protobuf bao gồm:

  • Lưu trữ dữ liệu một cách tối ưu
  • Tốc độ mã hoá và giải mã dữ liệu nhanh chóng
  • Hỗ trợ cho hầu hết các ngôn ngữ lập trình hiện tại
  • Tối ưu hoá dữ liệu thông qua các class được tạo tự động từ file .proto

Protobuf hỗ trợ nhiều ngôn ngữ, bao gồm:

  • C++
  • C#
  • Java
  • Kotlin
  • Python
  • Go
  • Dart

Khi sử dụng Protobuf, chúng ta có các tùy chọn sau:

  • Proto2: ngôn ngữ giao thức dùng để mã hoá dữ liệu có cấu trúc. Nó hỗ trợ tạo mã cho nhiều ngôn ngữ như C++, Python, …
  • Proto3: là phiên bản mới nhất của Protobuf, là sự phát triển của Proto2 với nhiều tính năng mới được thêm vào.

Vì Proto3 là phiên bản mới nhất, trong bài viết này, mình sẽ chỉ đề cập đến cú pháp của Proto3. Đối với Proto2, bạn có thể tham khảo tại đây.

Message

Mình sẽ đưa ra một ví dụ đơn giản về một message Person được định nghĩa trong Proto3.

syntax = "proto3";
message Person {
string name = 1;
int32 id = 2;
string email = 3;
}

Trong ví dụ trên, dòng đầu tiên định nghĩa phiên bản của Protobuf được sử dụng, ở đây là Proto3. Chúng ta có một message có tên là Person với các trường là name, email (kiểu dữ liệu string), và id (kiểu dữ liệu int32). Khi định nghĩa các trường cho message, chúng ta bắt buộc phải cung cấp tên và kiểu dữ liệu cho mỗi trường.

Field numbers

Chúng ta bắt buộc phải gán số cho các trường của message trong file .proto từ số 1 đến 536,870,911 như ví dụ trên, trong đó mình đã đánh số lần lượt là 1, 2, 3. Chúng ta có một số ràng buộc như sau:

  • Các số được gán phải là duy nhất (unique) trong các trường được định nghĩa.
  • Các số từ 19,000 đến 19,999 được dành riêng cho việc triển khai Protobuf. Khi sử dụng những số này, trình biên dịch sẽ báo lỗi.
  • Chúng ta không được sử dụng những số đã được dùng cho các trường reserved hoặc bất kỳ số nào đã được định nghĩa trong phần extension.
Có Thể Bạn Quan Tâm :   Năm, tháng, ngày, giờ, phút, giây, quý tiếng Anh là gì?

Các số này được gán là không thể thay đổi sau khi message này đã được sử dụng, vì Protobuf sử dụng những số này để mã hoá dữ liệu. Thay đổi những số này có nghĩa là xóa trường hiện tại và tạo một trường mới.

Chúng ta nên sử dụng những số từ 1 đến 15 để gán cho các trường trong message vì những số nhỏ chiếm ít không gian khi mã hoá dữ liệu. Ví dụ, các số từ 1 đến 15 chỉ chiếm 1 byte khi mã hoá, trong khi các số từ 16 đến 2,047 chiếm đến 2 byte. Bạn có thể tìm hiểu thêm về phần này trong phần Protocol Buffer Encoding trên trang chủ của Protobuf.

Field Rules

Các trường trong message có thể có một số ràng buộc như sau:

  • singular: là quy tắc mặc định khi không có quy tắc nào được định nghĩa. Trường này phải được cung cấp giá trị ban đầu, nếu không, trường sẽ không được khởi tạo.
  • optional: tương tự như singular, nhưng với optional, Protobuf sẽ kiểm tra xem trường này đã được đặt giá trị hay chưa. Nếu trường này đã được gán giá trị, nó sẽ được mã hoá vào dữ liệu. Nếu trường không được gán giá trị, nó sẽ không được mã hoá vào dữ liệu. Điều này có nghĩa là trường có thể có hoặc không có trong dữ liệu khi mã hoá.
  • repeated: trường này có thể lặp lại với số lần tùy ý.
  • map: là kiểu dữ liệu có dạng key/value.

Comments

Chúng ta có thể thêm comment vào file .proto bằng cách sử dụng // hoặc /* … */;

syntax = "proto3"; /* This is message Person */ message Person { string name = 1; // Name of the person int32 id = 2; string email = 3; }

Reserved Fields

Trong trường hợp chúng ta update một message bằng cách xóa một trường, hoặc comment trường đó ra khỏi message, có thể xảy ra tình huống là các nhà phát triển trong tương lai sử dụng lại các số trường đã được xóa khi cập nhật message. Điều này có thể gây ra một số vấn đề. Để tránh tình huống này, khi xóa các trường trong message, chúng ta nên thêm số của trường đó vào danh sách reserved. Để đảm bảo rằng với các kiểu dữ liệu JSON hoặc Text, trường được xóa vẫn được phân tích như dữ liệu, chúng ta sẽ thêm tên của trường đã xóa vào danh sách reserved. Dưới đây là một ví dụ về việc sử dụng reserved fields:

Có Thể Bạn Quan Tâm :   Quy trình chăm sóc da sau peel hiệu quả & sản phẩm nên dùng

message Employer { reserved 2, 15, 9 to 11; reserved "name", "email"; }

Trong ví dụ trên, vì mình vẫn muốn trường “name” và “email” vẫn được phân tích như dữ liệu với kiểu dữ liệu JSON hoặc Text, mình đã thêm hai trường này vào danh sách reserved dù chúng đã bị xóa. Và những số đã bị xóa ở đây là 2, 15, 9, 10, 11.

Values Type

Protobuf hỗ trợ hầu hết các kiểu dữ liệu bao gồm chuỗi số, số nguyên, số thực, boolean, enums, map, … Cú pháp này độc lập với các ngôn ngữ lập trình, cho phép các chương trình được viết bằng các ngôn ngữ khác nhau giao tiếp với nhau một cách đáng tin cậy. Bạn có thể tìm hiểu về toàn bộ kiểu dữ liệu được hỗ trợ tại đây.

Default Values

Khi một message được phân tích, nếu các trường không được gán giá trị, chúng ta sẽ có các giá trị mặc định sau cho từng kiểu dữ liệu:

  • string: chuỗi rỗng
  • bytes: byte rỗng
  • bool: giá trị false
  • numeric: giá trị mặc định là 0
  • Với message, nếu không có trường nào được định nghĩa, giá trị mặc định sẽ phụ thuộc vào ngôn ngữ khi biên dịch

Qua bài viết này, chúng ta đã tìm hiểu về khái niệm, công dụng và cách sử dụng của Protocol Buffers (Protobuf). Kiến thức trên chỉ là tổng hợp từ các nguồn khác nhau, nếu có bất kỳ sai sót nào, mong các bạn góp ý để bài viết được hoàn thiện hơn. Hy vọng rằng qua bài viết này, các bạn đã hiểu rõ hơn về Protobuf và cách nó hoạt động. Trong các bài viết tiếp theo, mình sẽ hướng dẫn sử dụng Protobuf khi triển khai hệ thống microservices, để các bạn thấy rõ hơn những lợi ích mà nó mang lại. Cảm ơn các bạn đã đọc đến cuối bài viết ❤️.

  • Tài liệu Protobuf
Back to top button