تحديد المشاكل في واجهة برمجة التطبيقات الخاصة بالبرامج الوسيطة وحلّها

تعرض معظم واجهات برمجة التطبيقات للبرامج الوسيطة كائن SdvResult. في حال النجاح، يحتوي هذا الكائن على كائن النتيجة المتوقّع. في حال حدوث خطأ، يحتوي هذا الكائن على كائن SdvStatus يشير إلى سلوك غير متوقّع أو حالة خطأ، وغالبًا ما يتم تحديد ذلك من خلال رمز خطأ، مثل Internal أو Unavailable أو DataLoss.

تساعدك هذه الصفحة في تحديد مشاكل رموز الخطأ هذه وحلّها.

تحديد مشاكل حالات فشل التسجيل والإنشاء وحلّها

تحدث حالات فشل التسجيل والإنشاء عادةً عند محاولة إنشاء خدمة غير صالحة أو تسجيلها.

يتعذّر إنشاء خدمة ثانية

الخطأ:

خطأ Internal

السبب:

أنت تحاول تسجيل مثيل حزمة الخدمة نفسه (الاسم ورقم تعريف المثيل) مرّتين.

الحلّ:

لا تحاول تسجيل مثيل حزمة الخدمة نفسه (الاسم ورقم تعريف المثيل) مرّتين.

يتعذّر حذف حزمة خدمة مكرّرة

الخطأ:

Status(-3, EX_ILLEGAL_ARGUMENT)

السبب:

أنت تحاول حذف حزمة خدمة مكرّرة غير متوفّرة.

الحلّ:

لا تحاول حذف حزمة خدمة مكرّرة غير متوفّرة.

يتعذّر استرداد مثيل ناشر لإرسال الرسائل

الخطأ:

يؤدي استدعاء take_publisher() إلى عرض none.

السبب:

لقد استدعيت take_publisher() مرّتين للنوع نفسه من مثيل حزمة الخدمة نفسه.

الحلّ:

لا تستدعِ take_publisher() مرّتين للنوع نفسه من مثيل حزمة الخدمة نفسه.

يتعذّر إنشاء `Subscriber` أو `Observer` أو `History` أو `InstantReader`

الخطأ:

خطأ Unavailable

السبب:

حاولت إنشاء Subscriber أو Observer أو History أو InstantReader لناشر غير متوفّر أو تم إلغاء تسجيله.

الحلّ:

تأكَّد من توفّر الناشر أو تسجيله قبل محاولة إنشاء Subscriber أو Observer أو History أو InstantReader له.

يتعذّر إنشاء عميل RPC

الخطأ:

خطأ Unavailable

السبب:

حاولت إنشاء عميل RPC لاسم وحدة خادم غير متوفّر أو غير مسجَّل.

الحلّ:

تأكَّد من توفّر الخادم وتسجيله قبل إنشاء عميل RPC.

تحديد مشاكل حالات فشل التواصل وحلّها

قد تحدث حالات فشل التواصل بعد تنفيذ خدمة وبدء التواصل مع خدمات أخرى.

تحديد مشاكل إلغاء تسجيل الناشر وحلّها

يمكن أن تحدث أخطاء عند إلغاء تسجيل ناشر بينما لا يزال القرّاء نشطين.

تعرض الدالة `read_next_messages()` في `Subscriber` قوائم فارغة

الخطأ:

تنجح الدالة read_next_messages() ولكنها تعرض قوائم فارغة.

السبب:

تم إلغاء تسجيل الناشر بينما لا يزال القرّاء نشطين.

الحلّ:

استخدِم مشتركًا أو سجلّاً يتضمّن تدفقًا للإتاحة. إذا كانت آخر رسالة في تدفق الإتاحة غير متوفّرة، يعني ذلك أنّه تم إلغاء تسجيل الناشر ولا تتوفّر أي رسائل جديدة.

تعرض الدالة `next()` في `Observer` خطأً داخليًا

الخطأ:

تعرض الدالة next() خطأً Internal.

السبب:

تم إلغاء تسجيل الناشر بينما لا يزال القرّاء نشطين.

الحلّ:

استخدِم مشتركًا أو سجلّاً يتضمّن تدفقًا للإتاحة. إذا كانت آخر رسالة في تدفق الإتاحة غير متوفّرة، يعني ذلك أنّه تم إلغاء تسجيل الناشر ولا تتوفّر أي رسائل جديدة.

لا تعرض الدالة `read_from_history()` في `History` رسائل جديدة

الخطأ:

لا تعرض الدالة read_from_history() أي رسائل جديدة، بل تعرض الرسائل القديمة فقط.

السبب:

تم إلغاء تسجيل الناشر بينما لا يزال القرّاء نشطين.

الحلّ:

استخدِم مشتركًا أو سجلّاً يتضمّن تدفقًا للإتاحة. إذا كانت آخر رسالة في تدفق الإتاحة غير متوفّرة، يعني ذلك أنّه تم إلغاء تسجيل الناشر ولا تتوفّر أي رسائل جديدة.

تعرض الدالة `read_latest_message()` في `InstantReader` خطأً داخليًا

الخطأ:

تعرض الدالة read_latest_message() خطأً Internal.

السبب:

تم إلغاء تسجيل الناشر بينما لا يزال القرّاء نشطين.

الحلّ:

استخدِم مشتركًا أو سجلّاً يتضمّن تدفقًا للإتاحة. إذا كانت آخر رسالة في تدفق الإتاحة غير متوفّرة، يعني ذلك أنّه تم إلغاء تسجيل الناشر ولا تتوفّر أي رسائل جديدة.

تحديد مشاكل قائمة الرسائل الفارغة وحلّها

يمكن أن تحدث أخطاء عند محاولة القراءة من قائمة رسائل فارغة.

تعرض الدالة `read_next_messages()` في `Subscriber` قائمة فارغة

الخطأ:

تعرض الدالة read_next_messages() قائمة فارغة بنجاح.

السبب:

الناشر نشط، ولكنّه لم يرسِل رسائل.

الحلّ:

استخدِم مشتركًا أو سجلّاً يتضمّن تدفقًا للإتاحة. إذا كانت آخر رسالة في تدفق الإتاحة متوفّرة، يعني ذلك أنّ الناشر نشط ولا تتوفّر أي رسائل جديدة.

تعرض الدالة `next()` في `Observer` خطأً داخليًا

الخطأ:

تعرض الدالة next() خطأً Internal.

السبب:

الناشر نشط، ولكنّه لم يرسِل رسائل.

الحلّ:

استخدِم مشتركًا أو سجلّاً يتضمّن تدفقًا للإتاحة. إذا كانت آخر رسالة في تدفق الإتاحة متوفّرة، يعني ذلك أنّ الناشر نشط ولا تتوفّر أي رسائل جديدة.

لا تعرض الدالة `read_from_history()` في `History` رسائل جديدة

الخطأ:

تعرض الدالة read_from_history() قائمة فارغة بنجاح.

السبب:

الناشر نشط، ولكنّه لم يرسِل رسائل.

الحلّ:

استخدِم مشتركًا أو سجلّاً يتضمّن تدفقًا للإتاحة. إذا كانت آخر رسالة في تدفق الإتاحة متوفّرة، يعني ذلك أنّ الناشر نشط ولا تتوفّر أي رسائل جديدة.

تعرض الدالة `read_latest_message()` في `InstantReader` خطأً داخليًا

الخطأ:

تعرض الدالة read_latest_message() خطأً Internal.

السبب:

الناشر نشط، ولكنّه لم يرسِل رسائل.

الحلّ:

استخدِم مشتركًا أو سجلّاً يتضمّن تدفقًا للإتاحة. إذا كانت آخر رسالة في تدفق الإتاحة متوفّرة، يعني ذلك أنّ الناشر نشط ولا تتوفّر أي رسائل جديدة.

تحديد مشاكل تجاوز سعة المخزن المؤقت أو فقدان البيانات وحلّها

يمكن أن تحدث أخطاء عندما يرسِل الناشر الرسائل بمعدّل أسرع من معدّل استهلاكها من قِبل القارئ.

تعرض أول عملية قراءة في `Subscriber` بعد تجاوز سعة المخزن المؤقت خطأً `DataLoss`

الخطأ:

تعرض الدالة read_next_message() خطأً DataLoss.

السبب:

يرسِل الناشر الرسائل بمعدّل أسرع من معدّل استهلاكها من قِبل القارئ.

الحلّ:

تعرض أول عملية `next()` في `Observer` بعد تجاوز سعة المخزن المؤقت خطأً `DataLoss`

الخطأ:

تعرض الدالة next() خطأً DataLoss.

السبب:

يرسِل الناشر الرسائل بمعدّل أسرع من معدّل استهلاكها من قِبل القارئ.

الحلّ: إليك بعض الحلول المحتمَلة:

  • ينشر الناشر بمعدّل أبطأ. على سبيل المثال، قد يكون لديك متغيّر يتضمّن الطابع الزمني لآخر رسالة. إذا كان الوقت الحالي أقل من آخر وقت نشر بالإضافة إلى قيمة دلتا، لا تنشر الرسالة. باستخدام هذه الآلية، يتم نشر رسالة واحدة على الأكثر لكل قيمة دلتا.

  • يستخدِم المستهلك كائن InstantRead بدلاً من مراقب. لا يعرض كائن InstantRead أخطاء تجاوز سعة المخزن المؤقت ويعرض دائمًا آخر رسالة. إذا كانت آخر رسالة هي الوحيدة التي تهمّك، يمكنك استخدام كائن InstantRead بدلاً من مراقب.

  • ينفِّذ المستهلك عملية أخذ العيّنات. إذا كان الحلّ يتضمّن ناشرًا (P1) ينشر الرسائل بمعدّل أسرع من معدّل قراءتها من قِبل المراقب (O1)، يمكنك إنشاء ناشر جديد (P2) ومراقب جديد (O2) لاستيعاب الاختلاف في سرعة النشر والقراءة.

    على سبيل المثال، لنفترض أنّ P1 ينشر رسالة كل 10 ملّي ثانية، ولكن لا يمكن لـ O1 قراءة رسالة واحدة إلا كل 100 ملّي ثانية ويتجاهل الرسائل التسع المتبقية. لحلّ هذا التباين، أنشئ حلاً يتّبع الخطوات التالية:

    1. ينشر P1 الرسائل إلى O2.
    2. يقرأ O2 رسالة واحدة ويتجاهل تسع رسائل.
    3. يرسِل O2 الرسالة التي تم قراءتها إلى P2.
    4. يرسِل P2 الرسالة التي تم قراءتها إلى O1.
    5. يقرأ O1 رسالة واحدة كل عشر ثوانٍ.

    يوضّح رمز المثال التالي كيفية تنفيذ سيناريو أخذ العيّنات هذا:

    int discarded_message = 10;
    
    while (true) {
    message m = O2.read_message();
    if discarded_message == 10 {
      discarded_message = 0;
      P2.publish(m);
    } else {
     discarded_message ++;
    }
    }
    

عمليات القراءة في `History` غير مكتملة

الخطأ:

تم فقدان الرسالة قبل نسخ السجلّ. ما مِن إشعار مباشر بالخطأ عند القراءة.

السبب:

يرسِل الناشر الرسائل بمعدّل أسرع من معدّل استهلاكها من قِبل القارئ.

الحلّ:

لا يقرأ `InstantReader` سوى آخر رسالة

الخطأ:

تم فقدان الرسالة قبل نسخ السجلّ. ما مِن إشعار مباشر بالخطأ عند القراءة.

السبب:

يرسِل الناشر الرسائل بمعدّل أسرع من معدّل استهلاكها من قِبل القارئ.

الحلّ:

لا ينطبق

يستدعي عميل RPC طريقة، ولكنّها غير متوفّرة

الخطأ:

يفشل طلب الإجراء بسبب الخطأ Unavailable.

السبب:

لا يعرف SDV اسم الخادم ويعرض Unavailable. تعرض البرنامج الوسيط هذا الخطأ إذا لم يعرض اكتشاف الخدمة اسم خادم صالحًا.

الحلّ:

ابدأ حزمة خدمة تحدّد server للواجهة المحدّدة التي يريد العميل استخدامها.

يعرض التنفيذ من جهة الخادم خطأً `SdvStatus`

الخطأ:

يعرض التنفيذ من جهة الخادم SdvResult يتضمّن خطأً SdvStatus ، مثل SdvStatusCode::NotFound. يتم نشر الخطأ مرة أخرى إلى العميل الذي استدعى الطريقة.

السبب:

يعمل SDV ونظام التواصل بين العميل والخادم على النحو المتوقّع، ولكنّ العميل قدّم طلبًا يؤدي إلى ظهور خطأ في الخادم.

الحلّ:

قدِّم طلبًا صالحًا باستخدام العميل أو أصلِح الخادم للاستجابة بنجاح لهذه الطلبات.