الرئيسية
» المجالات
»
كيفية إصلاح "خطأ مهلة واجهة برمجة التطبيقات" عند تشغيل مهام سير العمل متعددة الوكلاء
كيفية إصلاح "خطأ مهلة واجهة برمجة التطبيقات" عند تشغيل مهام سير العمل متعددة الوكلاء
نادرًا ما يُحلّ خطأ "انقطاع الاتصال بواجهة برمجة التطبيقات" في سير عمل متعدد الوكلاء بمجرد تغيير رقم واحد. قد يستدعي المخطط ثلاثة وكلاء، وقد يستدعي كل وكيل واجهة برمجة تطبيقات خاصة بـ LLM أو خدمة بحث أو قاعدة بيانات أو أداة، ويمكن لكل طبقة أن يكون لها مهلة زمنية خاصة بها، وسياسة إعادة محاولة، ومجموعة اتصالات، وحدود تزامن. يكمن الحل العملي في تحديد الطبقة التي تنتهي مهلتها أولًا، ثم الاختيار بين فترات انتظار أطول، أو عدد أقل من المكالمات المتزامنة، أو عمليات إعادة محاولة أكثر ذكاءً، أو مسار حرج أقصر، أو تصميم مهمة غير متزامنة.
المفاضلة مهمة: رفع مهلة زمنية أمر بسيط ولكنه يستهلك الموارد لفترة أطول؛ إعادة المحاولات المتكررة قد تزيد الحمل والتكلفة؛ تقليل التزامن يحسن الاستقرار ولكنه يقلل من ذروة الإنتاجية؛ الوكلاء المتوازيون يقللون زمن الاستجابة الفعلي فقط عندما تستطيع الخدمات اللاحقة استيعاب هذا الانتشار. لا يوجد إعداد واحد مثالي لكل نظام متعدد الوكلاء.
ما هو وقت انتهاء المهلة الذي تواجهه فعلياً؟
ابدأ بتصنيف حالات الفشل بدلاً من التعامل مع كل حالة انتهاء مهلة على أنها نفس الحدث. قد تنتهي مهلة عملاء HTTP أثناء الاتصال أو القراءة أو الكتابة أو انتظار اتصال من مجموعة اتصالات. على سبيل المثال، يوثق بروتوكول HTTPX أربعة أنواع منفصلة من حالات انتهاء المهلة: الاتصال، والقراءة، والكتابة، وانتظار الاتصال من مجموعة اتصالات. سلوكه الافتراضي هو إطلاق تنبيه انتهاء المهلة بعد خمس ثوانٍ من عدم نشاط الشبكة، وليس بالضرورة بعد خمس ثوانٍ من إجمالي مدة الطلب. راجع وثائق HTTPX الرسمية الخاصة بانتهاء المهلة .
إذا كنت تستخدم حزمة تطوير البرمجيات (SDK) الخاصة بلغة بايثون من OpenAI، فإن ملف README الرسمي الحالي ينص على أن مهلة العميل الافتراضية للطلبات هي 10 دقائق، وأن حالات فشل المهلة تُعاد محاولتها مرتين افتراضيًا. كما تعيد حزمة تطوير البرمجيات (SDK) تلقائيًا محاولة الاتصال في حالة أخطاء HTTP 408 و409 و429 و5xx مع فترة تأخير قصيرة. هذه إعدادات افتراضية لحزمة تطوير البرمجيات (SDK)، وليست ضمانًا بأن كل خادم وكيل أو موازن تحميل أو بوابة أو منسق أمام الطلب سينتظر 10 دقائق. راجع ملف README الرسمي لحزمة تطوير البرمجيات (SDK) الخاصة بلغة بايثون من OpenAI .
الخطوة 1: التقاط الاستثناء الدقيق والوكيل ونقطة النهاية وطبقة النقل التي انتهت مهلتها بدلاً من تسجيل فشل عام في سير العمل فقط.
ما هو الحل الذي يجب عليك اختياره؟
خيار
الأنسب
الفائدة الرئيسية
المقايضة الرئيسية
قم بزيادة مهلة الطلب
استدعاءات نموذج/أداة صحية ولكنها بطيئة بشكل ملحوظ
الحد الأدنى من تغييرات الكود والبنية
يظل العمال والاتصالات مشغولين لفترة أطول؛ وقد تقوم بوابة المصدر بإنهاء الطلب أولاً
أعد المحاولة مع التراجع الأسي
أخطاء الشبكة العابرة، وحدود معدل النقل، وحالات فشل محددة من فئة 5xx
يتعافى تلقائياً من الأعطال قصيرة الأجل
قد يؤدي ذلك إلى زيادة حركة البيانات، وزمن الاستجابة، والتكلفة؛ وهو غير آمن للإجراءات غير المتكررة إلا إذا تم تصميمه بعناية.
انخفاض تزامن الوكلاء
429 ثانية، مهلة تجميع البيانات، تشبع في اتجاه المصب
يقلل من الاندفاعات والازدحام في قائمة الانتظار
انخفاض ذروة الإنتاجية وأحيانًا وقت أطول لإكمال سير العمل
موازاة العوامل المستقلة
سير العمل المتسلسل ذو الفروع المستقلة
يختصر المسار الحرج
يزيد من عدد الطلبات المتزامنة وقد يؤدي إلى فرض قيود على معدل النقل أو الاتصال
مخرجات جزئية للبث
تجربة مستخدم تفاعلية حيث يكون زمن استجابة البايت الأول مهمًا
يرى المستخدمون التقدم بشكل أسرع
لا يحل هذا تلقائيًا مشكلة انتهاء مهلة التكامل الصعبة أو مشكلة ازدحام الخدمة النهائية.
نقل العمل إلى مهمة/قائمة انتظار غير متزامنة
سير العمل الذي قد يستغرق عشرات الثواني أو الدقائق
يفصل دورة حياة طلب HTTP عن دورة حياة سير العمل
يتطلب ذلك حالة الوظيفة، والاستطلاع/خطافات الويب، والتكرار، والاستمرارية، والمراقبة التشغيلية
الخطوة 1: ابحث عن الطبقة الأولى التي تتجاوز موعد تسليمها النهائي
سجّل معرّف ارتباط لسير العمل الكامل، ومعرّف نطاق أو معرّف فرعي لكل استدعاء وكيل وأداة. سجّل وقت البدء، ووقت الانتهاء، ونقطة النهاية، ورقم المحاولة، ونوع الاستثناء، وحالة الاستجابة إن وجدت، وما إذا كان الإلغاء قد جاء من المتصل أو الخدمة المستهدفة.
السؤال المهم هو: "من توقف عن الانتظار أولاً؟" إذا انتهت مكالمة LLM في 42 ثانية، لكن بوابة API توقفت عند 30 ثانية، فإن رفع مهلة عميل LLM من 60 إلى 120 ثانية لن يُغير شيئًا. تُشير وثائق أمازون الحالية لواجهات برمجة تطبيقات HTTP الخاصة ببوابة API إلى مهلة تكامل قصوى تبلغ 30 ثانية، وهو مثال جيد على سبب كون أقصر مهلة في السلسلة هي التي تُحدد النتيجة في كثير من الأحيان. راجع حصص واجهات برمجة تطبيقات HTTP الخاصة ببوابة API من أمازون .
الخطوة 2: رسم مسار الطلب وتحديد كل مكان يمكن أن ينهي أو يؤخر المكالمة: المنسق، والوكيل، والبوابة، وواجهة برمجة تطبيقات النموذج، وواجهة برمجة تطبيقات البحث، وقاعدة البيانات، وخدمة الأدوات.
الخطوة الثانية: قياس المسار الحرج، وليس فقط متوسط زمن الاستجابة
قد يبدو متوسط زمن الاستجابة جيدًا، بينما تتسبب نسبة ضئيلة من المكالمات البطيئة في معظم حالات فشل سير العمل. راقب على الأقل معدل نجاح كل تبعية، بالإضافة إلى زمن الاستجابة عند النسب المئوية 50 و95 و99. في مرحلة التوزيع، سجّل أيضًا وقت الانتظار في قائمة الانتظار ووقت انتظار مجمع الاتصالات، لأن "واجهة برمجة التطبيقات البطيئة" قد تكون في الواقع عميلًا مُثقلًا ينتظر اتصالًا متاحًا.
استخدم التتبعات للإجابة على ثلاثة أسئلة عملية: ما هي التبعية التي تهيمن على المسار الحرج، وما إذا كانت العوامل البطيئة المتعددة تعمل بالتسلسل عندما يمكن أن تعمل في وقت واحد، وما إذا كانت ارتفاعات التزامن تتوافق مع أخطاء 429 أو مهلة التجميع أو 5xx.
الخطوة 3: قارن زمن الاستجابة والأخطاء وحالة التبعية معًا؛ يشير ارتفاع مهلة الانتظار الذي يتزامن مع تبعية واحدة متدهورة إلى حل مختلف عن ارتفاع التزامن على مستوى النظام.
الخطوة 3: بناء ميزانية فترات الراحة من الخارج إلى الداخل
حدد أولاً موعداً نهائياً شاملاً لسير العمل، ثم قلل المواعيد النهائية الداخلية بحيث تفشل الطبقات الأدنى مبكراً بما يكفي لكي يتمكن المنسق من التعافي. على سبيل المثال، قد يخصص موعد نهائي مدته 120 ثانية للمستخدم 10 ثوانٍ للتنسيق ومعالجة الاستجابة، تاركاً 110 ثوانٍ للعمل الفعلي. قد يحصل استدعاء أداة فردية على 15 ثانية، بينما قد يحصل استدعاء نموذج على 45 أو 60 ثانية حسب زمن الاستجابة النهائي المُلاحظ.
لا تقم بنسخ هذه القيم بشكل أعمى؛ فهي مجرد مثال على طريقة وضع الميزانية، وليست قيمًا افتراضية عامة. اختر القيم بناءً على توزيع زمن الاستجابة المقاس ومستوى الخدمة المتفق عليه للمنتج. يجب أن يكون الموعد النهائي الخارجي طويلًا بما يكفي لاحتواء المكالمة الداخلية، وعدد محاولات إعادة الاتصال المسموح بها، وفترات التأخير، ووقت التنظيف.
يُتيح بايثون 3.11 والإصدارات الأحدث asyncio.timeout()إمكانية تحديد مهلة زمنية للعمليات غير المتزامنة. عند انقضاء هذه المهلة، يتم إلغاء المهمة ويُظهر مدير السياق إشعارًا TimeoutError. راجع توثيق مهلة asyncio الرسمي في بايثون .
الخطوة 4: قم بتكوين قيم المهلة الزمنية وإعادة المحاولة كميزانية منسقة بدلاً من زيادة كل قيمة بشكل مستقل.
الخطوة الرابعة: حدد الحد الأقصى للتزامن قبل زيادة عدد المحاولات
غالباً ما تفشل أنظمة الوكلاء المتعددين لأن انتشارها يتزايد بوتيرة أسرع من المتوقع. فإذا قام كل طلب من طلبات المستخدمين العشرين بتشغيل خمسة وكلاء، وقام كل وكيل بتشغيل أداتين، فقد يُنشئ النظام ما يصل إلى 200 استدعاء لاحق قبل إعادة المحاولة. إضافة عمليات إعادة المحاولة أولاً قد يُحوّل الازدحام إلى عاصفة من عمليات إعادة المحاولة.
يُعدّ مُحدِّد التزامن غالبًا الخيار الأمثل عند مواجهة استجابات 429، أو انتهاء مهلة التجميع، أو ازدياد وقت الانتظار، أو وصول تبعية لاحقة إلى حدّ التشبع. asyncio.Semaphoreتوفر لغة بايثون طريقة بسيطة تعتمد على العداد لتقييد عدد العمليات الفرعية التي تدخل قسمًا محميًا في وقت واحد. راجع توثيق الإشارات الرسمي في بايثون .
import asyncio
sem = asyncio.Semaphore(8)
async def guarded_agent_call(agent, task):
async with sem:
return await agent.run(task)
هذا التوازن مقصود: فالحد الأدنى يحمي الخدمات اللاحقة، لكنه قد يزيد من الازدحام داخل تطبيقك. لذا، اضبطه بما يتناسب مع معدل النقل، وزمن الاستجابة (p95)، وحدود المعدل، وسعة مجمع الاتصالات، بدلاً من اختيار أكبر رقم يمكن لجهازك جدولته.
الخطوة 5: قم بربط التزامن المحدود بإعدادات النقل الصريحة حتى لا تتنكر مجموعة الاتصالات الكاملة كنموذج أو أداة بطيئة.
الخطوة 5: أعد المحاولة فقط في حالات الفشل التي من المحتمل أن تنجح لاحقًا
تُعدّ إعادة المحاولة مفيدة في حالات انقطاع الاتصال المؤقت، وحدود معدل الطلبات، وأخطاء الخادم المحددة، وانتهاء مهلة الطلب، عندما يكون تكرار العملية آمنًا. لكنها تُعتبر خيارًا غير مناسب في حالات أخطاء التحقق، وفشل المصادقة، وأخطاء الأدوات المحددة، أو الإجراءات ذات التأثيرات الجانبية التي لا توفر حماية ضد التكرار.
انتبه لتكرار محاولات إعادة الاتصال. إذا قام SDK بإعادة الاتصال مرتين، فهذا يعني ما يصل إلى ثلاث محاولات لكل استدعاء منطقي. وإذا قامت طبقة الوكيل بإعادة الاتصال مرتين أيضًا، يصبح الحد الأقصى النظري تسع محاولات لتلك العملية المنطقية الواحدة: ثلاث محاولات خارجية مضروبة في ثلاث محاولات من SDK. وإذا قام المنسق بعد ذلك بإعادة الاتصال بمرحلة كاملة من خمسة وكلاء، فقد يزداد حجم الطلبات بسرعة.
مركز مسؤولية إعادة المحاولة حيثما أمكن. بالنسبة لاستدعاءات LLM باستخدام OpenAI Python SDK، تذكر أن SDK الحالي يعيد محاولة بعض أنواع الفشل مرتين افتراضيًا. أضف محاولة إعادة خارجية فقط عندما يكون لديك سبب محدد ويمكنك تحديد ميزانية المحاولات الإجمالية. citeturn212133view0turn212133view1
الخطوة 6: تصنيف الخطأ قبل إعادة المحاولة؛ قد يبرر انتهاء مهلة القراءة إعادة المحاولة المحدودة، بينما لا يبرر خطأ التكوين الدائم ذلك عادةً.
الخطوة 6: تقصير المسار الحرج دون التسبب في مشكلة التفرع
إذا تم تشغيل وكلاء التخطيط والبحث والتقييم والكتابة بالتتابع، فإن إجمالي زمن الاستجابة يساوي تقريبًا مجموع مدة كل منهم. ويمكن أحيانًا تشغيل فروع مستقلة بالتزامن، مما يقلل زمن الاستجابة الفعلي للفرع الأبطأ بدلاً من مجموع أزمنة جميع الفروع.
تُعدّ TaskGroup في بايثون asyncio.TaskGroupطريقةً مُهيكلةً لتشغيل المهام المُترابطة بشكلٍ مُتزامن. تُشير وثائق بايثون الحالية إلى أن TaskGroup تنتظر اكتمال المهام في المجموعة، وتُلغي المهام المُتبقية عند فشل إحداها باستثناءٍ غير قابلٍ للإلغاء، مما يُوفر سلوك أمانٍ أقوى من إنشاء المهام غير المُهيكل. راجع وثائق TaskGroup الرسمية في بايثون .
المعالجة المتوازية ليست مجانية. إذا فرض مزود الخدمة نفسه حدًا صارمًا لعدد الطلبات في الدقيقة أو عدد الطلبات المتزامنة، فقد يؤدي تشغيل أربعة وكلاء في وقت واحد إلى تحويل سير عمل بطيء ولكنه ناجح إلى تدفق سريع من استجابات 429. لذا، يُنصح بمعالجة الأعمال المستقلة فقط بالتوازي، مع الإبقاء على مُحدد التزامن العام مُفعلاً.
الخطوة 7: متى يجب عليك التوقف عن استخدام طلب HTTP متزامن؟
إذا كانت عمليات سير العمل الاعتيادية تتجاوز عادةً أقصر مهلة زمنية للطلبات في مسار الشبكة، فإن الانتقال إلى نموذج مهام غير متزامن يكون عادةً أكثر سلاسة من تمديد كل مهلة زمنية باستمرار. يمكن لطلب HTTP الأولي التحقق من صحة المدخلات، وإنشاء مهمة دائمة، وإرجاع مُعرّف المهمة فورًا. بعد ذلك، تُنفّذ العمليات الرسوم البيانية متعددة العوامل خارج دورة حياة الطلب، بينما يتلقى العميل معلومات التقدم من خلال الاستقصاء، أو الأحداث المُرسلة من الخادم، أو WebSockets، أو webhook.
يُعدّ البثّ مفيدًا عندما يستطيع الخادم البدء بإرسال مخرجات ذات معنى مبكرًا. على سبيل المثال، يدعم OpenAI Python SDK بثّ الأحداث المرسلة من الخادم لاستدعاءات واجهة برمجة تطبيقات الاستجابات. يُحسّن البثّ من سرعة الاستجابة المُدركة، ويُمكنه الحفاظ على اتصال نشط يُنتج البيانات، ولكنه لا يحلّ تلقائيًا مشكلة الحد الأقصى لعمر الطلب لكل خادم وكيل. راجع مرجع OpenAI الرسمي لبثّ الأحداث .
اختر مهمة غير متزامنة عندما تكون المتانة أهم من البساطة الفورية: مهام بحثية طويلة، وسير عمل الوكلاء الذي يتطلب موافقة بشرية، والعديد من استدعاءات الأدوات، والعمليات المكلفة التي لا ترغب في تكرارها، أو أحمال العمل التي يجب أن تستمر حتى بعد انقطاع اتصال العميل. ويكمن ثمن ذلك في إدارة حالة إضافية: حالة المهمة، ونقاط التحقق، ومفاتيح التكرار، والإلغاء، وتخزين النتائج، وملكية إعادة المحاولة.
الخطوة 7: بالنسبة لسير العمل الطويل، تتبع اكتمال الوكيل كحالة سير عمل دائمة بدلاً من الاعتماد على اتصال عميل واحد ليظل مفتوحًا حتى ينتهي كل وكيل.
الخطوة 8: التحقق من صحة الإصلاح تحت حمل واقعي
لا يُعتبر نجاح طلب واحد دليلاً على وجود حل. اختبر النظام عند مستوى التزامن المتوقع في بيئة الإنتاج، وقم بقياس معدل النجاح، ومعدل انتهاء المهلة، ومحاولات إعادة المحاولة لكل مهمة منطقية، وزمن الاستجابة عند 95 و99%، وتأخير قائمة الانتظار، ووقت انتظار مجمع الاتصالات، ومعدلات الأخطاء 429/5xx في اتجاه المصب، وتكلفة كل عملية مكتملة.
إذا كنت تُشغّل وكلاء في Kubernetes، فاستخدم اختبارات الجاهزية والحيوية لأغراض مختلفة. تُوثّق Kubernetes اختبارات الجاهزية باعتبارها الآلية التي تُحدّد ما إذا كان ينبغي لـ Pod استقبال حركة مرور، بينما تُحدّد اختبارات الحيوية متى يجب إعادة تشغيل الحاوية. تُحذّر وثائقها صراحةً من أن اختبارات الحيوية سيئة التنفيذ قد تُسبّب أعطالًا متتالية تحت الضغط. راجع وثائق اختبارات Kubernetes الرسمية .
في حالات التحميل الزائد المؤقت، غالباً ما يكون عدم الاستعداد أكثر أماناً من التسبب في موت متكرر لعمال أصحاء ولكنهم مشغولون. يجب حصر حالات انقطاع الخدمة في الحالات التي يكون فيها إعادة تشغيل العملية هو الإجراء الأمثل للتعافي.
الخطوة 8: التحقق من التغيير باستخدام مقاييس حركة المرور وزمن الاستجابة الشبيهة بالإنتاج، وليس فقط من خلال تشغيل اختبار ناجح واحد.
كيف يمكنك تحديد الحل المناسب لنمط الفشل لديك؟
النمط الملحوظ
التغيير الأول الأكثر فائدة
ما لا يجب فعله أولاً
تنتهي المكالمات بعد الموعد النهائي للعميل مباشرة؛ وتكون النتائج اللاحقة جيدة.
قم بزيادة مهلة الانتظار الداخلية المحددة وأعد تحديد ميزانية الموعد النهائي الخارجي
زيادة عدد المحاولات
تزداد أخطاء 429 ومهلات تجميع العمليات مع ازدياد التزامن
خفض التزامن وإضافة نظام الانتظار/التحكم في التدفق العكسي
قم بتشغيل المزيد من العملاء بالتوازي
أخطاء عرضية من نوع 408/5xx أو أعطال في الشبكة
استخدم محاولات إعادة محدودة ذات تراجع أسي للعمليات المتكررة.
أعد محاولة كل استثناء إلى أجل غير مسمى
تستغرق عملية سير العمل عادةً وقتًا أطول من حدود البوابة
استخدم بنية مهام غير متزامنة أو تصميم تدفق مدعوم
استمر في رفع مهلة SDK فقط
يهيمن أحد العوامل البطيئة على زمن استجابة p99
قم بتحسين هذا الاعتماد أو تخزينه مؤقتًا أو استبداله أو عزله؛ ضع في اعتبارك خيارًا احتياطيًا.
اضبط مهلات الوكلاء غير ذوي الصلة
لا تظهر حالات الفشل إلا بعد إضافة عوامل متوازية
حافظ على التوازي المفيد، ولكن أضف إشارة مرور عالمية وحدودًا لكل موفر.
افترض أن المعالجة المتوازية أسرع دائمًا
خط أساس عملي للإنتاج
بالنسبة لواجهة برمجة تطبيقات نموذجية متعددة الوكلاء، فإن الأساس القوي هو إعطاء كل سير عمل معرف ارتباط، وتتبع كل استدعاء للوكيل والأداة، وتحديد موعد نهائي واحد من البداية إلى النهاية، وتعيين مواعيد نهائية أقصر لكل استدعاء داخله، وفرض حد عالمي للتزامن لكل موفر في اتجاه المصب، والحفاظ على عمليات إعادة المحاولة محدودة ومتكررة، والاحتفاظ بحالة كافية لاستئناف أو الإبلاغ عن الإكمال الجزئي.
ثم اضبط النظام بناءً على القياسات. إذا كان النظام مستقرًا ولكنه بطيء جدًا، فقم بتنفيذ المهام المستقلة بالتوازي بشكل انتقائي. إذا كان سريعًا عند الأحمال المنخفضة ولكنه يتعطل عند ذروة الأحمال، فقلل من عدد عمليات التفرع وأضف آلية للتحكم في التدفق العكسي. إذا كانت عمليات سير العمل الناجحة تستغرق وقتًا أطول مما يسمح به مسار الطلب المتزامن، فقم بتغيير بنية النظام بدلًا من محاولة جعل كل خادم وسيط ينتظر لفترة أطول.