Protocol Buffers (Protobuf) एक बाइनरी सीरियलाइज़ेशन फ़ॉर्मेट है जो संरचित डेटा के लिए है, जिसे Google ने सेवाओं के बीच कुशल सूचना आदान-प्रदान के लिए विकसित किया है। इस फ़ॉर्मेट में .proto फ़ाइलों में स्कीमा की पूर्व-परिभाषा आवश्यक है, जिससे विभिन्न भाषाओं के लिए कोड जनरेट किया जाता है। Google के आधिकारिक दस्तावेज़ीकरण के अनुसार, Protobuf JSON से 3-10 गुना छोटे संदेश आकार प्रदान करता है। Protobuf का उपयोग gRPC, Google Maps और हज़ारों आंतरिक सेवाओं में किया जाता है।
मुख्य बिंदु
Protocol Buffers Google द्वारा विकसित एक संरचित डेटा सीरियलाइज़ेशन तंत्र है, जो JSON और XML के समान है, लेकिन एक मूलभूत अंतर के साथ: डेटा बाइनरी फ़ॉर्मेट में एन्कोड किया जाता है। इसका मतलब है कि Protobuf संदेश को नंगी आँखों से नहीं पढ़ा जा सकता, लेकिन यह काफी कम जगह लेता है और टेक्स्ट-आधारित समकक्षों की तुलना में तेज़ी से प्रोसेस होता है।
Protobuf को Google के अंदर सेवाओं के बीच डेटा आदान-प्रदान में प्रदर्शन समस्याओं को हल करने के लिए बनाया गया था। 2008 में, यह तकनीक कई भाषाओं के समर्थन के साथ एक ओपन-सोर्स प्रोजेक्ट बन गई: C++, Java, Python, Go, JavaScript, Kotlin, Swift, Dart और अन्य। 2016 में जारी किया गया proto3 संस्करण, सिंटैक्स को सरल बनाया और अधिक भाषाओं के लिए समर्थन जोड़ा।
Protobuf और JSON के बीच मुख्य अंतर डेटा आदान-प्रदान शुरू होने से पहले स्कीमा को परिभाषित करने की आवश्यकता है। स्कीमा फ़ाइल (.proto) संदेश संरचना का वर्णन करती है: फ़ील्ड, प्रकार और अद्वितीय फ़ील्ड नंबर। इस स्कीमा से, protoc कंपाइलर सीरियलाइज़ेशन और डीरियलाइज़ेशन के लिए लक्ष्य भाषा में क्लास जनरेट करता है।
Protobuf आर्किटेक्चर में तीन प्रमुख घटक शामिल हैं: स्कीमा परिभाषा भाषा (.proto), protoc कंपाइलर, और विशिष्ट भाषाओं के लिए रनटाइम लाइब्रेरी। डेवलपर .proto फ़ाइल में डेटा संरचना का वर्णन करता है, संकलन चलाता है, और इस डेटा के साथ काम करने के लिए तैयार क्लास प्राप्त करता है।
Protobuf संदेश में प्रत्येक फ़ील्ड का एक अद्वितीय नंबर (फ़ील्ड नंबर) होता है — यह एक अनुक्रमिक नंबर नहीं है, बल्कि एक टैग है जो बाइनरी फ़ॉर्मेट में फ़ील्ड की पहचान करने के लिए उपयोग किया जाता है। 1 से 15 तक के नंबर एक बाइट में एन्कोड होते हैं, 16 से 2047 तक — दो बाइट में। इसलिए, उच्च उपयोग आवृत्ति वाले महत्वपूर्ण फ़ील्ड को आकार अनुकूलन के लिए 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 के साथ काम करने के लिए Gradle में com.google.protobuf प्लगइन संस्करण 0.9+ का उपयोग किया जाता है। प्लगइन जोड़ने और .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 संदेश में पहचानकर्ता, नाम, मूल्य और श्रेणी सहित उत्पाद जानकारी होती है। बाइनरी फ़ॉर्मेट JSON की तुलना में प्रतिक्रिया आकार को 5-8 गुना कम करता है।
सर्वर साइड पर Protobuf के साथ gRPC सेवा का उदाहरण। सेवा GetProducts RPC विधि घोषित करती है, जो पेजिनेशन पैरामीटर के साथ अनुरोध स्वीकार करती है और उत्पादों की सूची लौटाती है। 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()
}
}
Android प्रोजेक्ट में Protobuf सेटअप com.google.protobuf Gradle प्लगइन के माध्यम से किया जाता है। प्लगइन बिल्ड के दौरान स्वचालित रूप से protoc कंपाइलर चलाता है और .proto फ़ाइलों से Kotlin क्लास जनरेट करता है। काम करने के लिए, आपको प्रोजेक्ट-स्तरीय build.gradle में प्लगइन जोड़ना होगा और इसे ऐप्लिकेशन मॉड्यूल में लागू करना होगा।
Gradle कॉन्फ़िगर करने के बाद, .proto फ़ाइलें src/main/proto निर्देशिका में रखी जाती हैं। protoc कंपाइलर प्रत्येक बिल्ड के दौरान उन्हें प्रोसेस करता है, Kotlin क्लास जनरेट करता है जिसका उपयोग ऐप्लिकेशन कोड में किया जा सकता है। प्रोजेक्ट की अन्य लाइब्रेरी के साथ निर्भरता टकराव से बचने के लिए protobuf और protoc संस्करणों को सही ढंग से निर्दिष्ट करना महत्वपूर्ण है।
iOS प्रोजेक्ट के लिए, Protobuf CocoaPods या Swift Package Manager के माध्यम से जोड़ा जाता है। Swift Protobuf प्लगइन स्वचालित रूप से Codable प्रोटोकॉल के अनुरूप Swift संरचनाएँ जनरेट करता है। Flutter के लिए Dart प्रोजेक्ट में, protobuf पैकेज का उपयोग किया जाता है, और संकलन dart run protoc_plugin के माध्यम से किया जाता है।
अक्सर पूछे जाने वाले प्रश्न
Protobuf एक बाइनरी फ़ॉर्मेट है जिसमें अनिवार्य स्कीमा है, JSON से 3-10 गुना अधिक संक्षिप्त। JSON टेक्स्ट-आधारित, मानव-पठनीय है और इसे स्कीमा की आवश्यकता नहीं है। Protobuf तेज़ी से सीरियलाइज़ और डीरियलाइज़ करता है लेकिन .proto फ़ाइलों के संकलन की आवश्यकता होती है। JSON डीबग करना आसान है और पूर्व-सेटअप की आवश्यकता नहीं है।
अपने प्लेटफ़ॉर्म के लिए protobuf GitHub रिलीज़ से protoc डाउनलोड करें। macOS के लिए, brew install protobuf के माध्यम से स्थापित करें। Windows के लिए, ज़िप आर्काइव डाउनलोड करें और protoc.exe को PATH में जोड़ें। Android/Kotlin के लिए, com.google.protobuf Gradle प्लगइन का उपयोग करें, जो बिल्ड के दौरान स्वचालित रूप से संकलन चलाता है।
gRPC Google द्वारा एक उच्च-प्रदर्शन RPC फ्रेमवर्क है जो Protobuf को अपनी इंटरफ़ेस परिभाषा भाषा (IDL) और सीरियलाइज़ेशन फ़ॉर्मेट के रूप में उपयोग करता है। gRPC .proto फ़ाइलों में सेवाओं और RPC विधियों को परिभाषित करता है, क्लाइंट और सर्वर कोड जनरेट करता है, और स्ट्रीमिंग और बाइनरी प्रोटोकॉल का समर्थन करता है।
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 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें