الردود على الأخطاء

استجابات الخطأ العادية

إذا نجح طلب البيانات من واجهة برمجة التطبيقات، ستعرض واجهة برمجة التطبيقات رمز الحالة 200. في حال حدوث خطأ في أحد الطلبات، تعرض واجهة برمجة التطبيقات رمز حالة HTTP والحالة والسبب في الاستجابة استنادًا إلى نوع الخطأ. بالإضافة إلى ذلك، يحتوي نص الاستجابة على وصف تفصيلي لسبب الخطأ. إليك مثال على استجابة خطأ:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "invalidParameter",
    "message": "Invalid value '-1' for max-results. Value must be within the range: [1, 1000]",
    "locationType": "parameter",
    "location": "max-results"
   }
  ],
  "code": 400,
  "message": "Invalid value '-1' for max-results. Value must be within the range: [1, 1000]"
 }
}

جدول الأخطاء

الرمز السبب الوصف الإجراء المقترَح
400 invalidParameter يشير إلى أنّ معلَمة الطلب تتضمّن قيمة غير صالحة. يقدّم الحقلان locationType وlocation في استجابة الخطأ معلومات عن القيمة غير الصالحة. يُرجى عدم إعادة المحاولة بدون حلّ المشكلة. تحتاج إلى توفير قيمة صالحة للمَعلمة المحدّدة في استجابة الخطأ.
400 badRequest يشير إلى أن طلب البحث غير صالح. على سبيل المثال، رقم التعريف الرئيسي غير متوفّر أو لم تكن مجموعة السمات أو المقاييس المطلوبة صالحة. يُرجى عدم إعادة المحاولة بدون حلّ المشكلة. عليك إجراء تغييرات على طلب بحث واجهة برمجة التطبيقات لكي يعمل.
401 invalidCredentials تشير هذه القيمة إلى أنّ الرمز المميّز للمصادقة غير صالح أو منتهي الصلاحية. يُرجى عدم إعادة المحاولة بدون حلّ المشكلة. يجب الحصول على رمز مصادقة جديد.
403 insufficientPermissions يشير إلى أنّ المستخدم لا يملك أذونات كافية للكيان المحدّد في طلب البحث. يُرجى عدم إعادة المحاولة بدون حلّ المشكلة. يجب الحصول على أذونات كافية لتنفيذ العملية على العنصر المحدّد.
403 dailyLimitExceeded يشير إلى أن المستخدم قد تجاوز الحصة اليومية (إما لكل مشروع أو لكل ملف شخصي (ملف شخصي)). يُرجى عدم إعادة المحاولة بدون حلّ المشكلة. لقد استهلكت حصتك اليومية. يُرجى الاطِّلاع على حدود واجهة برمجة التطبيقات وحصصها.
403 userRateLimitExceeded يشير إلى أنّه تمّ تجاوز الحدّ الأقصى لطلبات البحث لكل 100 ثانية لكل مستخدم. القيمة التلقائية المحدَّدة في وحدة تحكُّم واجهة Google API هي 100 طلب بحث لكل 100 ثانية لكل مستخدم. يمكنك زيادة هذا الحدّ الأقصى في وحدة التحكم في واجهة Google API إلى 1,000 كحدّ أقصى. أعِد المحاولة باستخدام ميزة الرقود الأسي الثنائي. عليك إبطاء المعدّل الذي ترسل به الطلبات.
403 rateLimitExceeded يشير إلى تجاوز حدود معدّل طلبات البحث لكل 100 ثانية في المشروع. أعِد المحاولة باستخدام ميزة الرقود الأسي الثنائي. عليك إبطاء المعدّل الذي ترسل به الطلبات.
403 quotaExceeded يشير إلى أنّه تم الوصول إلى 10 طلبات متزامنة لكل ملف شخصي (ملف شخصي) في Core Reporting API. أعد المحاولة باستخدام ميزة exponential backoff. عليك الانتظار حتى يكتمل طلب واحد قيد التقدم على الأقل لهذا الملف الشخصي (الملف الشخصي).
500 internalServerError حدث خطأ غير متوقّع في الخادم الداخلي. لا تحاول تنفيذ هذا الطلب أكثر من مرة.
503 backendError عرَض الخادم خطأ. لا تحاول تنفيذ هذا الطلب أكثر من مرة.

التعامل مع 500 أو 503 ردّ

قد يظهر الخطأ 500 أو 503 أثناء الحِمل الثقيل أو مع طلبات أكبر حجمًا وأكثر تعقيدًا. بالنسبة إلى الطلبات الأكبر حجمًا، يمكنك طلب البيانات لفترة زمنية أقصر. يمكنك أيضًا تنفيذ خوارزمية الرقود الأسي الثنائي. ويمكن أن يعتمد معدل تكرار هذه الأخطاء على الملف الشخصي (الملف الشخصي) ومقدار بيانات إعداد التقارير المرتبطة بهذا الملف الشخصي، فالطلب الذي يتسبب في حدوث خطأ 500 أو 503 لملف شخصي واحد لن يؤدي بالضرورة إلى حدوث خطأ لطلب البحث نفسه بملف شخصي مختلف (ملف شخصي).

تنفيذ التراجع الأسي

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

في ما يلي تدفق تنفيذ خوارزمية الرقود الأسي البسيط.

  1. تقديم طلب إلى واجهة برمجة التطبيقات
  2. تلقّي استجابة خطأ تتضمّن رمز خطأ يمكن إعادة المحاولة
  3. الانتظار لمدة ثانية واحدة + random_number_milliseconds ثانية
  4. إعادة محاولة الطلب
  5. تلقّي استجابة خطأ تتضمّن رمز خطأ يمكن إعادة المحاولة
  6. الانتظار لمدة ثانيتين + random_number_milliseconds ثانية
  7. إعادة محاولة الطلب
  8. تلقّي استجابة خطأ تتضمّن رمز خطأ يمكن إعادة المحاولة
  9. الانتظار لمدة 4 ثوانٍ + random_number_milliseconds ثانية
  10. إعادة محاولة الطلب
  11. تلقّي استجابة خطأ تتضمّن رمز خطأ يمكن إعادة المحاولة
  12. الانتظار لمدة 8 ثوانٍ + random_number_milliseconds ثانية
  13. إعادة محاولة الطلب
  14. تلقّي استجابة خطأ تتضمّن رمز خطأ يمكن إعادة المحاولة
  15. الانتظار لمدة 16 ثانية + random_number_milliseconds ثانية
  16. إعادة محاولة الطلب
  17. في حال استمرار ظهور الخطأ، يمكنك إيقافه وتسجيله.

في المسار أعلاه، يكون random_number_milliseconds عددًا عشوائيًا من المللي ثانية أقل من أو يساوي 1000. وهذا أمر ضروري لتجنُّب أخطاء قفل معيّنة في بعض عمليات التنفيذ المتزامنة. يجب إعادة تعريف random_number_milliseconds بعد كل انتظار.

ملاحظة: يتم ضبط وقت الانتظار دائمًا على ( 2 ^ n) + random_number_milliseconds، حيث يشير n إلى عدد صحيح متزايد الزيادة بشكل منتظم، ويتم تحديده في البداية على أنّه 0، بينما تتم زيادته بمقدار 1 لكل تكرار (كل طلب).

يتم تعيين الخوارزمية على الانتهاء عندما يكون n هو 5. ولا يتم تطبيق هذا الحدّ الأقصى إلّا لمنع العملاء من إعادة المحاولة بشكل غير محدود، ما يؤدي إلى تأخير إجمالي بمقدار 32 ثانية تقريبًا قبل أن يُعدّ الطلب "خطأً لا يمكن إصلاحه".

رمز Python التالي هو تنفيذ الخطوات الواردة أعلاه لاسترداد الأخطاء التي تحدث في طريقة تُسمى makeRequest.

import random
import time
from apiclient.errors import HttpError

def makeRequestWithExponentialBackoff(analytics):
  """Wrapper to request Google Analytics data with exponential backoff.

  The makeRequest method accepts the analytics service object, makes API
  requests and returns the response. If any error occurs, the makeRequest
  method is retried using exponential backoff.

  Args:
    analytics: The analytics service object

  Returns:
    The API response from the makeRequest method.
  """
  for n in range(0, 5):
    try:
      return makeRequest(analytics)

    except HttpError, error:
      if error.resp.reason in ['userRateLimitExceeded', 'quotaExceeded',
                               'internalServerError', 'backendError']:
        time.sleep((2 ** n) + random.random())
      else:
        break

  print "There has been an error, the request never succeeded."