0Pricing
PHP Academy · درس

تواصل الخدمات: REST وgRPC

صِل الخدمات بشكل متزامن وفعّال

تواصل الخدمات: REST وgRPC درس مجاني في PHP Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في PHP Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة PHP Academy 4 دروس في المجموع.

REST وgRPC

تحتاج الخدمات إلى التواصل بشكل متزامن: يخرج طلب وتعود إجابة. والخياران المهيمنان هما REST عبر HTTP/JSON وgRPC عبر HTTP/2 + Protobuf. وهما محسّنان لأمور مختلفة — REST لسهولة الوصول والوضوح للمستخدم، وgRPC للسرعة والعقود الصارمة.

يعرض هذا الدرس كليهما من منظور PHP، ومتى ينبغي اختيار كل منهما.

REST: لغة التواصل المشتركة

يمثّل REST الموارد خلف عناوين URL، ويستخدم أفعال HTTP ورموز الحالة للتعبير عن الدلالة. ومن نقاط قوته: أدوات عالمية، وإمكانية التخزين المؤقت، وسهولة تصحيح الأخطاء باستخدام curl، وعدم الحاجة إلى عميل خاص. أما نقاط ضعفه فتشمل JSON المطوّل، وغياب مخطط مفروض، واقتصاره على الطلب والاستجابة.

بالنسبة إلى واجهات برمجة التطبيقات العامة ونقاط النهاية الموجهة للمتصفح، يكون REST هو الخيار الصحيح في معظم الحالات.

استدعاء خدمة REST

استخدموا عميل HTTP وفق PSR-18 (نستخدم Guzzle هنا). واضبطوا دائمًا مهلة للاتصال والطلب — إذ قد يؤدي استدعاء غير محدود المدة إلى نظير بطيء إلى استنفاد عمال PHP-FPM لديكم والتسبب في تعطل متسلسل.

<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;

$http = new Client([
    'base_uri'        => 'http://customers-svc/',
    'connect_timeout' => 1.0,  // never block forever on connect
    'timeout'         => 3.0,  // total request budget
    'http_errors'     => false,
]);

$res = $http->get('customers/42', ['headers' => ['Accept' => 'application/json']]);
if ($res->getStatusCode() === 200) {
    $customer = json_decode((string) $res->getBody(), true);
    echo $customer['email'] . "\n";
}

رموز الحالة هي العقد

في REST بين الخدمات، تُعد رموز حالة HTTP بروتوكول الأخطاء لديكم. تعاملوا معها بوعي:

  • 2xx نجاح؛ 4xx خطأ من جهة المستدعي (لا تعيدوا المحاولة دون تفكير)؛ أما 5xx/المهلات الزمنية فهي قابلة لإعادة المحاولة.
  • استخدموا 409 للتعارضات، و422 للتحقق، و429 لحدود المعدل (واحترموا Retry-After).

إعادة محاولة 400 تهدر الاستدعاءات فحسب؛ أما إعادة محاولة 503 مع التراجع التدريجي فهي التصرف الصحيح.

<?php
function isRetryable(int $status): bool {
    return $status === 0          // timeout/connection error
        || $status === 429
        || ($status >= 500 && $status !== 501);
}
var_dump(isRetryable(503)); // true
var_dump(isRetryable(400)); // false

gRPC: قائم على العقد أولًا وسريع

يستخدم gRPC Protocol Buffers: إذ تعرّفون الخدمات والرسائل في ملف .proto، ثم تولّدون وحدات عميل/خادم محددة الأنواع بقوة. وباستخدام HTTP/2 وProtobuf الثنائي، يكون أكثر ضغطًا وأقل زمنًا للاستجابة بكثير من JSON، كما أنه يدعم البث.

syntax = "proto3";
package customers;

service Customers {
  rpc GetCustomer (GetCustomerRequest) returns (Customer);
}

message GetCustomerRequest { string id = 1; }
message Customer {
  string id = 1;
  string email = 2;
  int32  loyalty_points = 3;
}

توليد Stubs لـ PHP

ثبّتوا إضافة gRPC الخاصة بـ PHP وإضافة protoc، ثم ولّدوا أصناف العميل من ملف .proto. يمكن لـ PHP أن يعمل بوصفه عميل gRPC متكاملًا عبر ext-grpc؛ أما تشغيل خادم gRPC أصلي بلغة PHP فيحتاج عادةً إلى Roadrunner أو Swoole.

pecl install grpc
composer require grpc/grpc google/protobuf

protoc --proto_path=. \
  --php_out=./generated \
  --grpc_out=./generated \
  --plugin=protoc-gen-grpc=$(which grpc_php_plugin) \
  customers.proto

استدعاء عميل gRPC

توفر لكم وحدات Stubs المولّدة طلبات واستجابات محددة الأنواع. ويعيد استدعاء gRPC الرسالة وكائنًا باسم status — فتحققوا دائمًا من رمز الحالة قبل الوثوق بالاستجابة.

<?php
require 'vendor/autoload.php';
use Customers\CustomersClient;
use Customers\GetCustomerRequest;
use Grpc\ChannelCredentials;

$client = new CustomersClient('customers-svc:50051', [
    'credentials' => ChannelCredentials::createInsecure(),
]);

$req = (new GetCustomerRequest())->setId('42');
[$reply, $status] = $client->GetCustomer($req)->wait();

if ($status->code === \Grpc\STATUS_OK) {
    echo $reply->getEmail(), "\n";
} else {
    fwrite(STDERR, "gRPC error: {$status->details}\n");
}

تطور المخطط

صُمّم Protobuf للتوافق إلى الأمام والخلف — إذا التزمتم بقواعده:

  • لا تعيدوا استخدام رقم حقل أو تغيّروه مطلقًا. أضيفوا الحقول الجديدة بأرقام جديدة.
  • علّموا الحقول المحذوفة باستخدام reserved حتى لا يمكن إعادة استخدام الرقم.
  • يتجاهل العملاء القدامى الحقول غير المعروفة؛ وتأخذ الحقول المفقودة القيم الافتراضية لأنواعها.

لا يوفر لكم JSON/REST أيًا من ذلك مجانًا — إذ تفرضون التوافق بالاتفاقية (ويُفضّل أن تستخدموا مخطط OpenAPI مشتركًا مع اختبارات عقود).

message Customer {
  string id = 1;
  string email = 2;
  reserved 3;            // old 'loyalty_points', never reuse 3
  reserved "loyalty_points";
  string display_name = 4; // new field, safe additive change
}

البث

يدعم gRPC أربعة أنواع من الاستدعاءات؛ بينما يدعم REST أصلاً النوع الأول فقط:

  • أحادي — طلب واحد واستجابة واحدة.
  • بث من الخادم — طلب واحد وتدفق من الاستجابات (مثل التحديثات المباشرة).
  • بث من العميل — تدفق من الطلبات واستجابة واحدة (مثل الرفع الجماعي).
  • ثنائي الاتجاه — يبث الطرفان بالتزامن.

إذا كانت حالة الاستخدام تتطلب دفعًا أو تدفق بيانات طويل الأمد، فإن بث gRPC يتفوق على استطلاع نقطة نهاية REST.

تمرير السياق والمهلات النهائية

تشكّل الاستدعاءات المتزامنة سلاسل، لذا يجب أن ينتقل شيئان مع كل طلب: معرّف ارتباط/تتبّع للتتبّع من البداية إلى النهاية، ومهلة نهائية حتى لا تجعل خدمة طرفية بطيئة السلسلة بأكملها معلّقة. يوفّر gRPC مهلات نهائية مدمجة، أما في REST فتحاكونها بميزانية مهلة متناقصة تُمرَّر إلى الخدمات التابعة.

<?php
// REST: shrink the remaining budget as the call chain deepens
function forwardHeaders(array $incoming, float $remainingMs): array {
    return [
        'X-Correlation-Id' => $incoming['X-Correlation-Id'] ?? bin2hex(random_bytes(8)),
        // downstream must finish within what's left of our budget
        'X-Timeout-Ms'     => (string) max(0, (int) $remainingMs),
    ];
}
print_r(forwardHeaders(['X-Correlation-Id' => 'trace-9'], 1500));

الاختيار بينهما

دليل عملي لاتخاذ القرار:

  • REST لواجهات برمجة التطبيقات العامة أو الخاصة بالشركاء، وعملاء المتصفح، وعمليات CRUD البسيطة، وسهولة تصحيح الأخطاء، والدعم الواسع للتخزين المؤقت.
  • gRPC للاستدعاءات الداخلية بين الخدمات ذات الحجم الكبير والزمن المنخفض، والعقود الصارمة محددة الأنواع، والبث.

تشغّل أنظمة كثيرة كليهما: gRPC خلف البوابة بين الخدمات، وREST عند الحافة للعالم الخارجي. لا تفرضوا على أداة أداء مهمة الأداة الأخرى.

تحقّق سريع

مطابقة البروتوكول لحالة الاستخدام.

مراجعة

التواصل المتزامن بين الخدمات:

  • REST/JSON — عالمي، سهل التصحيح، وقابل للتخزين المؤقت؛ رموز الحالة هي العقد؛ واضبطوا المهلات دائمًا.
  • gRPC/Protobuf — قائم على العقد أولًا، ومضغوط، وسريع، ويدعم البث؛ ولّدوا وحدات PHP محددة الأنواع.
  • حدّدوا قابلية إعادة المحاولة من رموز الحالة/gRPC؛ ولا تعيدوا محاولة أخطاء العميل مطلقًا.
  • طوّروا المخططات بإضافات فقط — ولا تعيدوا استخدام أرقام حقول Protobuf مطلقًا.
  • يُعد استخدام REST عند الحافة وgRPC بين الخدمات الداخلية تقسيمًا شائعًا وسليمًا.

التالي: توجيه كل هذه الخدمات وتحديد مواقعها باستخدام البوابات وآليات الاكتشاف.

الأسئلة الشائعة

هل درس «تواصل الخدمات: REST وgRPC» مجاني؟

نعم — نص درس «تواصل الخدمات: REST وgRPC» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة PHP Academy، انتقل إلى CoddyKit PRO. تتضمن دورة PHP Academy 4 دروس في المجموع.

ماذا ستتعلم في «تواصل الخدمات: REST وgRPC»؟

صِل الخدمات بشكل متزامن وفعّال تتمرن على PHP Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ PHP Academy؟

لا تُشترط خبرة سابقة. PHP Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «تواصل الخدمات: REST وgRPC»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس PHP Academy هذا؟

نعم. كل درس في PHP Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. من التطبيق الأحادي إلى الخدمات المصغّرة
  2. تواصل الخدمات: REST وgRPC
  3. بوابات API واكتشاف الخدمات
  4. المرونة: قواطع الدائرة وإعادة المحاولة
← العودة إلى PHP Academy