Το Protocol Buffers (Protobuf) είναι μια δυαδική μορφή σειριοποίησης δομημένων δεδομένων, που αναπτύχθηκε από την Google για αποτελεσματική ανταλλαγή πληροφοριών μεταξύ υπηρεσιών. Η μορφή απαιτεί προκαθορισμό σχήματος σε αρχεία .proto, από τα οποία δημιουργείται κώδικας για διάφορες γλώσσες. Σύμφωνα με την επίσημη τεκμηρίωση της Google, το Protobuf παρέχει μέγεθος μηνύματος 3-10 φορές μικρότερο από το JSON. Protobuf χρησιμοποιείται στο gRPC, στους Χάρτες Google και σε χιλιάδες εσωτερικές υπηρεσίες.
Κύρια σημεία
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 έχει έναν μοναδικό αριθμό (field number) — δεν είναι τακτικός αριθμός, αλλά μια ετικέτα που χρησιμοποιείται στη δυαδική μορφή για την αναγνώριση του πεδίου. Οι αριθμοί από 1 έως 15 κωδικοποιούνται με ένα byte, από 16 έως 2047 με δύο bytes. Γι' αυτό σημαντικά πεδία με υψηλή συχνότητα χρήσης θα πρέπει να αριθμούνται από 1 έως 15 για βελτιστοποίηση μεγέθους.
Το Protobuf υποστηρίζει ένα ευρύ φάσμα τύπων: βαθμωτοί (int32, int64, float, double, bool, string, bytes), απαριθμήσεις (enum), σύνθετοι (message) και ειδικοί (oneof, map). Κάθε τύπος έχει μια συγκεκριμένη δυαδική αναπαράσταση, βελτιστοποιημένη για το αντίστοιχο σενάριο χρήσης.
| Τύπος .proto | Τύπος C++ | Java/Kotlin | Περιγραφή |
|---|---|---|---|
| double | double | double | Αριθμός κινητής υποδιαστολής 64-bit |
| float | float | float | Αριθμός κινητής υποδιαστολής 32-bit |
| int32 | int32 | int | 32-bit, variable-length encoding |
| int64 | int64 | long | 64-bit, variable-length encoding |
| string | string | String | Συμβολοσειρά UTF-8 |
| bytes | string | ByteString | Αυθαίρετα bytes |
| bool | bool | boolean | true / false |
Protobuf προσφέρει τρία βασικά πλεονεκτήματα έναντι των μορφών κειμένου: μέγεθος μηνύματος, ταχύτητα σειριοποίησης και αυστηρή τυποποίηση. Σε συστήματα υψηλού φορτίου και εφαρμογές κινητών με περιορισμένη κίνηση, αυτά τα πλεονεκτήματα γίνονται κρίσιμα.
Η δυαδική αναπαράσταση Protobuf χρησιμοποιεί variable-length encoding (Varint) για αριθμούς: οι μικροί αριθμοί καταλαμβάνουν 1 byte, οι μεγάλοι έως 10 bytes. Αυτό επιτρέπει αποτελεσματική κωδικοποίηση αναγνωριστικών, σημαιών και μετρητών που σε JSON ή XML θα καταλάμβαναν δεκάδες bytes ως συμβολοσειρές κειμένου. Για παράδειγμα, ο αριθμός 150 στο Protobuf καταλαμβάνει 2 bytes, στο JSON 3 bytes (ως κείμενο “150”), στο XML 3 bytes + ετικέτες.
Ένα πρόσθετο πλεονέκτημα είναι η προς τα πίσω συμβατότητα. Η προσθήκη νέου πεδίου σε ένα σχήμα δεν σπάει τους παλιούς πελάτες: απλά αγνοούν τα άγνωστα πεδία. Η διαγραφή πεδίου απαιτεί μόνο τη δέσμευση του αριθμού του για αποφυγή συγκρούσεων στο μέλλον.
Το σχήμα .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. Το πρόσθετο εκκινεί αυτόματα τον μεταγλωττιστή protoc κατά τη μεταγλώττιση και δημιουργεί κλάσεις 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 — δυαδική μορφή με υποχρεωτικό σχήμα, 3-10 φορές πιο συμπαγής από το JSON. 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. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης