Protocol Buffers (Protobuf) — یک فرمت دودویی سریالیسازی دادههای ساختاریافته است که توسط Google برای تبادل مؤثر اطلاعات بین خدمات طراحی شده است. این فرمت نیازمند تعریف قبلی شما در فایلهای .proto است، که از آنها کد برای زبانهای مختلف تولید میشود. به گزارش مستندات رسمی Google، Protobuf اندازه پیامها را 3-10 برابر کوچکتر از JSON تامین میکند. 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 و کتابخانههای runtime برای زبانهای مخصوص. توسعهدهنده ساختار داده را در فایل .proto توصیف میکند، کامپایل را اجرا میکند و کلاسهای آماده برای کار با این دادهها را دریافت میکند.
هر صحنه در پیام Protobuf یک شماره منحصر به فرد (field number) دارد — این شماره ترتیب نیست، بلکه برچسبی است که در فرمت دودویی برای شناسایی صحنه استفاده میشود. شمارههای 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-bit, variable-length encoding |
| int64 | int64 | long | 64-bit, variable-length encoding |
| string | string | String | رشته UTF-8 |
| bytes | string | ByteString | بایتهای دلخواه |
| bool | bool | boolean | true / false |
Protobuf سه مزیت کلیدی نسبت به فرمتهای متنی ارائه میدهد: اندازه پیام، سرعت سریالیسازی و تایپ سختگیرانه. در سیستمهای با بار بالا و نرمافزارهای موبایل با ترافیک محدود، این مزایا به مرتبه حیاتی میشوند.
نمایش دودویی Protobuf از variable-length encoding (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 شامل اطلاعات محصول، از جمله شناسایی، نام، قیمت و دسته است. فرمت دودویی اندازه پاسخ را در مقایسه با JSON 5-8 برابر کاهش میدهد.
نمونه خدمت 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 را در زمان کامپایل اجرا کرده و از فایلهای .proto کلاسهای Kotlin تولید میکند. برای کار نیاز است پلاگین را در 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 از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید