Protobuf — ما هو تنسيق البيانات الثنائية ومبدأ العمل

المؤلف: IT Sectr نُشر: 2026-03-08 وقت القراءة: 8 دق

Protocol Buffers (Protobuf) هو تنسيق ثنائي لتسلسل البيانات المهيكلة، طورته Google للتبادل الفعال للمعلومات بين الخدمات. يتطلب التنسيق تعريف مخطط مسبق في ملفات .proto، والتي يتم من خلالها إنشاء كود للغات المختلفة. وفقاً للتوثيق الرسمي من Google، يوفر Protobuf أحجام رسائل أصغر 3-10 مرات من JSON. يُستخدم Protobuf في gRPC و Google Maps وآلاف الخدمات الداخلية.

النقاط الرئيسية

  • Protobuf — تنسيق ثنائي من Google للتسلسل بتمثيل بيانات مضغوط
  • مخططات .proto — وصف مقيد بشدة لهيكل البيانات مع ترجمة إلى كود
  • الأداء — تسلسل أسرع 3-10 مرات وأكثر ضغطاً من JSON
  • التوافق العكسي — تطور المخططات دون كسر العملاء الحاليين
  • gRPC — تقنية النقل الرئيسية لـ Protobuf في الخدمات المصغرة

ما هي Protocol Buffers؟

Protocol Buffers هي آلية تسلسل بيانات مهيكلة طورتها Google، مشابهة لـ JSON و XML، ولكن مع اختلاف جوهري: يتم ترميز البيانات بتنسيق ثنائي. هذا يعني أن رسالة Protobuf لا يمكن قراءتها بالعين المجردة، لكنها تشغل مساحة أقل بكثير وتُعالج بشكل أسرع من النظيرات النصية.

تم إنشاء Protobuf داخل Google لحل مشكلات الأداء في تبادل البيانات بين الخدمات. في عام 2008، أصبحت التقنية مشروعاً مفتوح المصدر مع دعم العديد من اللغات: C++ و Java و Python و Go و JavaScript و Kotlin و Swift و Dart وغيرها. الإصدار proto3، الذي صدر في 2016، بسّط الصياغة وأضاف دعماً لمزيد من اللغات.

الفرق الرئيسي بين Protobuf و JSON هو الحاجة إلى تعريف مخطط قبل بدء تبادل البيانات. يصف ملف المخطط (.proto) هيكل الرسالة: الحقول والأنواع والأرقام الفريدة للحقول. من هذا المخطط، يقوم المترجم protoc بتوليد فئات في اللغة الهدف للتسلسل وإلغاء التسلسل.

النظام البيئي لـ Protobuf

  • gRPC — إطار RPC عالي الأداء يستخدم Protobuf افتراضياً
  • protoc — مترجم مخططات .proto إلى كود بلغات برمجة مختلفة
  • Google API — معظم واجهات Google العامة تستخدم Protobuf
  • Envoy Proxy — يستخدم Protobuf للتكوين وتبادل البيانات

هندسة Protobuf

هندسة Protobuf تتضمن ثلاثة مكونات رئيسية: لغة تعريف المخطط (.proto)، والمترجم protoc، ومكتبات وقت التشغيل للغات محددة. يصف المطور هيكل البيانات في ملف .proto، ويشغّل الترجمة، ويتلقى فئات جاهزة للعمل مع هذه البيانات.

كل حقل في رسالة Protobuf له رقم فريد (رقم الحقل) — ليس رقمًا تسلسليًا، بل علامة تُستخدم في التنسيق الثنائي لتحديد الحقل. الأرقام من 1 إلى 15 تُرمّز ببايت واحد، من 16 إلى 2047 ببايتين. لذلك، يجب ترقيم الحقول المهمة عالية الاستخدام من 1 إلى 15 لتحسين الحجم.

أنواع بيانات Protobuf

يدعم 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

مخطط .proto يصف هيكل البيانات بلغة خاصة. يبدأ الملف بتحديد الصياغة (proto3) والحزمة وتبعيات الاستيراد. يتم تعريف كل رسالة بالكلمة المفتاحية message مع حقول، حيث لكل حقل نوع واسم ورقم فريد.

ممارسات المخطط الجيدة: أرقام الحقول من 1 إلى 15 للحقول كثيرة الاستخدام، أسماء ذات معنى، تجميع الحقول ذات الصلة في رسالة منفصلة، استخدام oneof للحقول التي يمكن أن تكون واحدة فقط من عدة خيارات.

protobuf
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 سيحتوي على بيانات المستخدم داخلياً. دعم التداخل يسمح بوصف هياكل هرمية معقدة دون تكرار التعريفات.

protobuf
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;
}

توليد الكود من .proto

المترجم 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 جاهزة للاستخدام في التطبيق.

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

Protobuf فعال بشكل خاص في بنية الخدمات المصغرة والتطبيقات المحمولة. لنأخذ سيناريو نموذجياً: تطبيق محمول يتلقى قائمة منتجات من الخادم عبر gRPC. تحتوي رسالة Protobuf على معلومات المنتج بما في ذلك المعرف والاسم والسعر والفئة. يقلل التنسيق الثنائي حجم الاستجابة بمقدار 5-8 مرات مقارنة بـ JSON.

خدمة gRPC في Kotlin

مثال لخدمة gRPC مع Protobuf على جانب الخادم. تعلن الخدمة عن طريقة RPC GetProducts، التي تستقبل طلباً مع معاملات الترقيم وتعيد قائمة بالمنتجات. تستخدم تطبيق Kotlin فئات مولّدة للعمل مع الطلبات والردود.

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

إعداد 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 و JSON؟

Protobuf هو تنسيق ثنائي بمخطط إلزامي، أكثر ضغطاً من JSON بمقدار 3-10 مرات. JSON نصي، قابل للقراءة البشرية، ولا يتطلب مخططاً. Protobuf يتسلسل ويلغي التسلسل بشكل أسرع لكنه يتطلب ترجمة ملفات .proto. JSON أسهل في التصحيح ولا يتطلب إعداداً مسبقاً.

كيفية تثبيت المترجم protoc؟

قم بتنزيل protoc من إصدار GitHub لـ protobuf وفق منصتك. لنظام macOS، ثبت عبر brew install protobuf. لنظام Windows، قم بتنزيل الأرشيف المضغوط وأضف protoc.exe إلى PATH. لنظام Android/Kotlin، استخدم إضافة Gradle com.google.protobuf، التي تشغل الترجمة تلقائياً أثناء البناء.

ما هو gRPC وكيف يرتبط بـ Protobuf؟

gRPC هو إطار RPC عالي الأداء من Google يستخدم Protobuf كلغة تعريف واجهة (IDL) وتنسيق تسلسل. يعرّف gRPC الخدمات وطرق RPC في ملفات .proto، ويولّد كود العميل والخادم، ويدعم البث والبروتوكولات الثنائية.

ما اللغات التي يدعمها Protobuf؟

مدعوم رسمياً من 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)، أضف حقولاً جديدة بأرقام جديدة. يتجاهل العملاء القدامى الحقول غير المعروفة، ويحصل العملاء الجدد على قيم افتراضية للحقول القديمة المفقودة.

الخلاصة

  • Protocol Buffers — تنسيق تسلسل ثنائي من Google مع مخطط بيانات إلزامي
  • حجم الرسالة أصغر 3-10 مرات من JSON بفضل ترميز Varint
  • سرعة التسلسل وإلغاء التسلسل أعلى من التنسيقات النصية
  • مخططات .proto توفر كتابة مقيدة وتوليد كود لأكثر من 12 لغة
  • التوافق العكسي يسمح بتطور API دون كسر العملاء
  • gRPC يستخدم Protobuf كتنسيق قياسي للتواصل بين الخدمات المصغرة
  • مثالي للأنظمة عالية التحميل والتطبيقات المحمولة ذات حركة المرور المحدودة

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا