Protocol Buffers (Protobuf) เป็นรูปแบบการเรียงลำดับแบบไบนารีสำหรับข้อมูลที่มีโครงสร้าง พัฒนาโดย Google สำหรับการแลกเปลี่ยนข้อมูลที่มีประสิทธิภาพระหว่างบริการต่าง ๆ รูปแบบนี้ต้องการกำหนดโครงสร้างล่วงหน้าในไฟล์ .proto ซึ่งจะถูกใช้สร้างโค้ดสำหรับภาษาต่าง ๆ ตาม เอกสารอย่างเป็นทางการของ Google โปรตอบัฟให้ขนาดข้อความเล็กกว่า JSON 3-10 เท่า Protobuf ถูกใช้ใน gRPC, Google Maps และบริการภายในนับพันราย
หัวข้อสำคัญ
Protocol Buffers เป็นกลไการเรียงลำดับข้อมูลที่มีโครงสร้างที่ Google พัฒนาขึ้น คล้ายกับ JSON และ XML แต่มีข้อแตกต่างสำคัญ: ข้อมูลถูกเข้ารหัสในรูปแบบไบนารี ซึ่งหมายความว่าข้อความ Protobuf ไม่สามารถอ่านด้วยตาเปล่า แต่ใช้พื้นที่น้อยกว่าและประมวลผลได้เร็วกว่าแบบที่อิงข้อความ
Protobuf ถูกสร้างภายใน Google เพื่อแก้ไขปัญหาด้านประสิทธิภาพในการแลกเปลี่ยนข้อมูลระหว่างบริการ ในปี 2008 เทคโนโลยีนี้กลายเป็นโปรเจคโอเพนซอร์สที่รองรับหลายภาษา: C++, Java, Python, Go, JavaScript, Kotlin, Swift, Dart และอื่น ๆ เวอร์ชัน proto3 ที่เปิดตัวในปี 2016 ทำให้ไวยากรณง่ายขึ้นและเพิ่มการรองรับภาษามากขึ้น
ความแตกต่างหลักระหว่าง Protobuf และ JSON คือความจำเป็นต้องกำหนดโครงสร้างก่อนเริ่มการแลกเปลี่ยนข้อมูล ไฟล์โครงสร้าง (.proto) อธิบายโครงสร้างข้อความ: ฟิลด์, ชนิด และหมายเลขฟิลด์ที่ไม่ซ้ำกัน จากโครงสร้างนี้ คอมไพล์เตอร์ protoc จะสร้างคลาสในภาษาเป้าหมายสำหรับการเรียงลำดับและการเรียงลำดับกลับ
สถาปัตยกรรม Protobuf ประกอบด้วยส่วนสำคัญสามส่วน: ภาษาการกำหนดโครงสร้าง (.proto), คอมไพล์เตอร์ protoc และไลบรารีขณะทำงานสำหรับภาษาเฉพาะ ผู้พัฒนาอธิบายโครงสร้างข้อมูลในไฟล์ .proto จากนั้นรันการคอมไพล์ และได้คลาสที่พร้อมใช้งานสำหรับการทำงานกับข้อมูลเหล่านี้
แต่ละฟิลด์ในข้อความ Protobuf มีหมายเลขเฉพาะ (หมายเลขฟิลด์) — ไม่ใช่หมายเลขลำดับ แต่เป็นแท็กที่ใช้ในรูปแบบไบนารีเพื่อระบุฟิลด์ หมายเลข 1 ถึง 15 ถูกเข้ารหัสด้วย 1 ไบท์, หมายเลข 16 ถึง 2047 — ด้วย 2 ไบท์ ดังนั้น ฟิลด์ที่สำคัญที่ใช้บ่อยควรได้รับหมายเลข 1 ถึง 15 เพื่อประสิทธิภาพด้านขนาด
Protobuf รองรับชนิดของข้อมูลที่หลากหลาย: แบบสคาลาร์ (int32, int64, float, double, bool, string, bytes), แบบเลขจำนวน (enum), แบบผสม (message) และแบบพิเศษ (oneof, map) แต่ละชนิดมีการแสดงออกแบบไบนารีแฉเฉพาะที่ได้รับการปรับเหมาะสำหรับกรณีการใช้งานที่เกี่ยวข้อง
| ชนิด .proto | ชนิด C++ | Java/Kotlin | คำอธิบาย |
|---|---|---|---|
| double | double | double | ตัวเลขทศนิยม 64 บิต |
| float | float | float | ตัวเลขทศนิยม 32 บิต |
| int32 | int32 | int | 32 บิต, การเข้ารหัสแบบความยาวประเพิ่งได้ |
| int64 | int64 | long | 64 บิต, การเข้ารหัสแบบความยาวประเพิ่งได้ |
| string | string | String | สตริง UTF-8 |
| bytes | string | ByteString | ไบท์ที่ต้องการ |
| bool | bool | boolean | true / false |
Protobuf ให้ข้อดีหลักสามประการเมื่อเทียบกับรูปแบบที่อิงข้อความ: ขนาดข้อความ, ความเร็วในการเรียงลำดับ และการกำหนดชนิดอย่างเข้มงวด ในระบบที่มีภาระสูงและแอปพลิเคชันมือถือที่มีทราฟิกจำกัด ข้อดีเหล่านี้กลายเป็นสิ่งสำคัญ
การแสดงออกแบบไบนารีของ Protobuf ใช้การเข้ารหัสแบบความยาวประเพิ่งได้ (Varint) สำหรับตัวเลข: ตัวเลขเล็กใช้ 1 ไบท์, ตัวเลขใหญ่ใช้สูงสุด 10 ไบท์ ทำให้สามารถเข้ารหัสตัวระบุประจำตัว, แฟล็ก และตัวนับได้อย่างมีประสิทธิภาพ ซึ่งใน JSON หรือ XML จะใช้หลายสิบไบท์เป็นสตริงข้อความ ตัวอย่างเช่น, ตัวเลข 150 ใน Protobuf ใช้ 2 ไบท์, ใน JSON — 3 ไบท์ (เป็นข้อความ “150”), ใน XML — 3 ไบท์ + แท็ก
ข้อดีเพิ่มเติมคือความเข้ากันได้ย้อนหลัง การเพิ่มฟิลด์ใหม่ในโครงสร้างไม่ทำลายคลายอน์ต์เก่า: พวกมันเพียงละเว้นฟิลด์ที่ไม่รู้จัก การลบฟิลด์ต้องการเฉพาะการสำรองหมายเลขของมันเพื่อหลีกเล่าการชนกันในอนาคต
โครงสร้าง .proto อธิบายโครงสร้างข้อมูลในภาษาเฉพาะ ไฟล์เริ่มต้นด้วยการระบุไวยากรณ์ (proto3), แพ็กเกจ และการนำเข้าขึ้งพึ่ง แต่ละข้อความถูกกำหนดด้วยคำสำคัญ message พร้อมฟิลด์โดยแต่ละฟิลด์มีชนิด, ชื่อ และหมายเลขที่ไม่ซ้ำกัน
แนวปฏิบัติโครงสร้างที่ดี: หมายเลขฟิลด์ 1 ถึง 15 สำหรับฟิลด์ที่ใช้บ่อย, ชื่อที่มีความหมาย, การจับกลุ่มฟิลด์ที่เกี่ยวข้องกันไว้ใน message แยกต่างหาก, การใช้ oneof สำหรับฟิลด์ที่สามารถเป็นได้เพียงหนึ่งในหลายตัวเลือก
syntax = "proto3";
package mobileapp;
message User {
string user_id = 1;
string name = 2;
string email = 3;
int32 age = 4;
UserRole role = 5;
repeated string tags = 6;
map<string, string> metadata = 7;
}
enum UserRole {
USER_ROLE_UNSPECIFIED = 0;
USER_ROLE_USER = 1;
USER_ROLE_ADMIN = 2;
USER_ROLE_MODERATOR = 3;
}
ข้อความสามารถซ้อนกันได้: ฟิลด์ profile ชนิด Profile จะมีข้อมูลผู้ใช้อยู่ภายใน การรองรับการซ้อนกันช่วยให้สามารถอธิบายโครงสร้างแบบลำดับชั้นที่ซับซ้อนโดยไม่ต้องทำซ้ำคำจำกัดความ
syntax = "proto3";
package mobileapp;
message Order {
string order_id = 1;
repeated OrderItem items = 2;
double total_price = 3;
PaymentInfo payment = 4;
}
message OrderItem {
string product_id = 1;
string title = 2;
int32 quantity = 3;
double price = 4;
}
message PaymentInfo {
string method = 1;
string transaction_id = 2;
double amount = 3;
}
คอมไพล์เตอร์ protoc แปลงไฟล์ .proto เป็นโค้ดต้นฉบับในภาษาเป้าหมาย สำหรับ Kotlin/Java ใช้พารามิเตอร์ --java_out, สำหรับ Swift ใช้ --swift_out (ผ่านปลั๊กอิน Apple Swift Protobuf), สำหรับ Dart ใช้ --dart_out คลาสที่สร้างขึ้นมีเมทอด builder สำหรับการสร้างข้อความและเมทอดการเรียงลำดับ/การเรียงลำดับกลับ
บน Android การทำงานกับ Protobuf ใช้ปลั๊กอิน com.google.protobuf เวอร์ชัน 0.9+ ใน Gradle หลังจากเพิ่มปลั๊กอินและระบุไฟล์ .proto แล้ว, การสร้างจะสร้างคลาส Kotlin ที่พร้อมใช้งานในแอปพลิเคชันโดยอัตโนมัติ
import com.google.protobuf.kotlin.toByteString
import com.example.mobileapp.UserOuterClass.User
fun createUser(): User {
return User.newBuilder()
.setUserId("usr_001")
.setName("IT Sectr")
.setEmail("team@itsectr.com")
.setAge(5)
.setRole(UserOuterClass.UserRole.USER_ROLE_ADMIN)
.addTags("mobile")
.addTags("backend")
.build()
}
fun serializeAndDeserialize(user: User): User {
// การเรียงลำดับเป็นรูปแบบไบนารี
val bytes = user.toByteArray()
// การเรียงลำดับกลับจากรูปแบบไบนารี
return User.parseFrom(bytes)
}
Protobuf มีประสิทธิภาพโดยเฉพาะในสถาปัตยกรรมไมโครเซร์วิซและแอปพลิเคชันมือถือ พิจารณาสถานการณ์ทั่วไป: แอปพลิเคชันมือถือรับรายการสินค้าจากเซิร์ฟเวอร์ผ่าน gRPC ข้อความ Protobuf มีข้อมูลสินค้ารวมถึงตัวระบุประจำตัว, ชื่อ, ราคา และหมวดหมู่ รูปแบบไบนารีช่วยลดขนาดการตอบสนองได้ 5-8 เท่าเมื่อเทียบกับ JSON
ตัวอย่างบริการ gRPC กับ Protobuf ทางฝั่งเซิร์ฟเวอร์ บริการประกาศเมทอด RPC ชื่อ GetProducts ซึ่งรับคำขอที่มีพารามิเตอร์การแบ่งหน้าและส่งคืนรายการสินค้า การนำไปใช้ใน Kotlin ใช้คลาสที่สร้างขึ้นสำหรับการทำงานกับคำขอและคำตอบ
import com.example.mobileapp.ProductServiceGrpcKt
import com.example.mobileapp.ProductOuterClass.Product
import com.example.mobileapp.ProductOuterClass.GetProductsRequest
import com.example.mobileapp.ProductOuterClass.GetProductsResponse
class ProductService : ProductServiceGrpcKt.ProductServiceCoroutineImplBase() {
override suspend fun getProducts(
request: GetProductsRequest
): GetProductsResponse {
val products = fetchProductsFromDb(
page = request.page,
limit = request.limit
)
return GetProductsResponse.newBuilder()
.addAllProducts(products)
.setTotalCount(products.size)
.build()
}
}
การตั้งค่า Protobuf ในโปรเจค Android ทำได้ผ่านปลั๊กอิน Gradle com.google.protobuf ปลั๊กอินจะทำงานโดยอัตโนมัติในระหว่างการสร้างและสร้างคลาส Kotlin จากไฟล์ .proto เพื่อให้ทำงานคุณต้องเพิ่มปลั๊กอินไปใน build.gradle ระดับโปรเจคและนำไปใช้ในโมดูลแอปพลิเคชัน
หลังจากการตั้งค่า Gradle, ไฟล์ .proto จะถูกวางไว้ในไดเรกทอรี่ src/main/proto คอมไพล์เตอร์ protoc จะประมวลผลแต่ละครั้งที่มีการสร้าง, สร้างคลาส Kotlin ที่สามารถใช้ในโค้ดแอปพลิเคชันได้ สิ่งสำคัญคือการระบุเวอร์ชันของ protobuf และ protoc อย่างถูกต้องเพื่อหลีกเล่าการขัดแย้งของการพึ่งพากับไลบรารีอื่นของโปรเจค
สำหรับโปรเจค iOS, Protobuf เชื่อมต่อผ่าน CocoaPods หรือ Swift Package Manager ปลั๊กอิน Swift Protobuf จะสร้างโครงสร้าง Swift ที่สอดคล้องกับโปรโตคอล Codable โดยอัตโนมัติ ในโปรเจค Dart สำหรับ Flutter จะใส่แพ็คเกจ protobuf และการคอมไพล์จะทำผ่าน dart run protoc_plugin
คำถามที่พบบ่อย
Protobuf เป็นรูปแบบไบนารีที่มีโครงสร้างที่จำเป็น, กะทัดรัดกว่า JSON 3-10 เท่า JSON เป็นข้อความ, อ่านได้โดยมนุษย์ และไม่ต้องการโครงสร้าง Protobuf เรียงลำดับและเรียงลำดับกลับได้เร็วกว่า แต่ต้องการการคอมไพล์ไฟล์ .proto JSON แก้ไขข้อผิดพลาดได้ง่ายกว่าและไม่ต้องการตั้งค่าล่วงหน้า
ดาวน์โหลด protoc จากการเปลี่ยนแปลง GitHub ของ protobuf สำหรับแพลตฟอร์มของคุณ สำหรับ macOS, ติดตั้งผ่าน brew install protobuf สำหรับ Windows, ดาวน์โหลดไฟล์ zip และเพิ่ม protoc.exe ใน PATH สำหรับ Android/Kotlin, ใช้ปลั๊กอิน Gradle com.google.protobuf ซึ่งจะทำงานคอมไพล์โดยอัตโนมัติในระหว่างการสร้าง
gRPC เป็นเฟรมเวิร์ก RPC สมรรถนะสูงของ Google ที่ใช้ Protobuf เป็นภาษานิยามส่วนติดต่อ (IDL) และรูปแบบการเรียงลำดับ gRPC กำหนดบริการและเมทอด RPC ในไฟล์ .proto, สร้างโค้ดคลายอน์ต์และเซิร์ฟเวอร์, และรองรับการสตรีมและโปรโตคอลไบนารี
Google รองรับอย่างเป็นทางการ: C++, Java, Kotlin, Python, Go, Ruby, C#, PHP, JavaScript, Objective-C, Swift และ Dart ชุมชนได้พัฒนาการรองรับสำหรับ Rust, TypeScript, Scala, Lua และภาษาอื่น ๆ สำหรับการพัฒนามือถือ, มี Kotlin/Java (Android) และ Swift/Objective-C (iOS) ให้เลือก
Protobuf รองรับความเข้ากันได้ย้อนหลังผ่านกฎเหล่านี้: อย่าเปลี่ยนหมายเลขฟิลด์, อย่าลบฟิลด์ (ใช้ reserved), เพิ่มฟิลด์ใหม่ด้วยหมายเลขใหม่ คลายอน์ต์เก่าจะละเว้นฟิลด์ที่ไม่รู้จัก, คลายอน์ต์ใหม่จะได้รับค่าเริ่มต้นสำหรับฟิลด์เก่าที่ขาดไป
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ