مرحبا بالجميع،
أنا أبني سير عمل n8n تعتمد بشكل كبير على واجهات برمجية خارجية، وأحاول إيجاد طريقة موثوقة للتعامل مع حدود المعدل دون إبطاء سير العمل بأكمله.
على سبيل المثال، قد تعيد واجهة برمجية:
{
“status”: 429,
“message”: “Too Many Requests”,
“retry_after”: 30
}
مخاوفي الرئيسية هي:
تجنب محاولات إعادة محاولة غير ضرورية
الامتثال لحدود معدل واجهة برمجية
منع واجهة برمجية واحدة بطيئة من حجب سير عمل آخر
معالجة الأعطال المؤقتة دون فقدان البيانات
أنا أفكر في التراجع الأسي، وقوائم الانتظار للطلبات، وتحديد التزامن.
بالنسبة لأولئك الذين يقومون بتشغيل n8n في الإنتاج:
كيف تتعاملون عادة مع استجابات 429؟
هل تستخدمون قائمة انتظار أم تعيدون المحاولة ببساطة مع التأخيرات؟
كيف تقررون الحد الأقصى لعدد المحاولات؟
هل وجدتم طريقة جيدة لمنع واجهة برمجية واحدة من أن تصبح اختناقًا لمثيل n8n بأكمله؟
وصف المشكلة/الخطأ/السؤال
ما رسالة الخطأ (إن وجدت)؟
يرجى مشاركة سير العمل الخاص بك
(حدد العقد على لوحة الرسم الخاصة بك واستخدم اختصارات لوحة المفاتيح CMD+C/CTRL+C و CMD+V/CTRL+V لنسخ ولصق سير العمل.)
@Greg_John طلبات HTTPS لها أوقات إعادة محاولة مع انتظار، يمكنك استخدام ذلك لمساعدتك، لكن لا يمكنك حقاً تسريع حدود المعدل ما لم يكن لديك خطة أعلى. يمكنك إعداده بحيث يقومون بالمعالجة الدفعية، وإعادة المحاولة عند الفشل، + ستساعدك عقد الانتظار!
إعداد سير عمل معالجة الأخطاء يمكن أن يساعد أيضاً في جعل المراقبة أسهل!
إجابات جيدة أعلاه. بعض الأشياء التي تعالج على وجه التحديد مخاوفك بشأن واجهة برمجية واحدة بطيئة تحجب سير العمل الآخر:
عزل التنفيذ لكل واجهة برمجية باستخدام سير عمل فرعية
الفكرة الأساسية: لا تتعامل مع حدود المعدل داخل سير العمل الرئيسي. انقل كل استدعاء واجهة برمجية خارجية إلى سير عمل فرعي خاص به (عقدة تنفيذ سير العمل). يبقى التدفق الرئيسي سريعًا؛ يتعامل سير العمل الفرعي مع منطق إعادة المحاولة الخاص به ويمكنه العمل بشكل مستقل دون حجب التنفيذات المتوازية الأخرى.
تتبع حالة الحصة عبر التنفيذات
إعادة محاولة HTTP المدمجة تتعامل فقط مع الأخطاء العابرة. لإدارة حد معدل حقيقي عبر التنفيذات المتزامنة، تحتاج إلى حالة تستمر بين التشغيلات:
قبل استدعاء واجهة برمجية، اقرأ الحصة المتبقية من مخزن القيم الرئيسية (صف Airtable، Redis عبر HTTP، أو جدول Google)
إذا كانت الحصة قريبة من الفراغ، اكتب طابع زمني “تهدئة حتى” وتخطَّ
بعد استدعاء ناجح، قلل العداد
هذا يمنع تنفيذات سير عمل متزامنة متعددة من إرهاق حصة واجهة البرمجية نفسها في نفس الوقت.
نمط قاطع الدائرة
أضف فحص قاطع دائرة في وقت مبكر من سير العمل الفرعي للواجهة البرمجية:
اقرأ علم “حالة الدائرة” من مخزن القيم الرئيسية
إذا كان `مفتوحًا` (مُشغَّل بعد N من 429s المتتالية)، أرجع خطأ منظمًا على الفور دون لمس واجهة برمجية
سير عمل مجدول منفصل يعيد تعيين العلم بعد انقضاء فترة التهدئة
هذا ما يمنع واجهة برمجية محدودة المعدل من التسبب في أعطال متسلسلة في كل ما يعتمد عليها.
قائمة الرسائل غير المُسلَّمة
بعد الحد الأقصى لمحاولات إعادة المحاولة، لا تسجل الخطأ فحسب — اكتب الحمولة الفاشلة إلى جدول Airtable أو قائمة انتظار webhook. يعيد سير عمل استرجاع منفصل محاولة هذه على جدول زمني، أو يعلمها للمراجعة عبر Slack.
نهج المراجعة الخلفية الأسية + عقدة الانتظار الذي حدده @Niffzy سليم لطبقة إعادة المحاولة. طبقة قاطع الدائرة + الحالة الخارجية هي ما يجعلها آمنة للإنتاج عندما تشارك سير عمل متعددة نفس حصة واجهة برمجية.
-–
إذا كان هذا نظامًا حيث يكون للأعطال تكلفة حقيقية (طلبات مفقودة، محفزات مفقودة)، فهذا هو نوع المعمارية التي نتعامل معها في عمليات البناء الكاملة على [occelatus.io/automate](Automation Services — Occelatus Labs). يسعدني الإجابة على الأسئلة هنا على أي حال.
إجابات جيدة أعلاه بشأن التراجع وعزل سير العمل الفرعي. ثلاثة أشياء تسبب مشاكل في الإنتاج ولم تظهر بعد.
لا تعيد محاولة كل فشل. فقط 429 و 5xx تستحق إعادة المحاولة. سيفشل 400 و 401 و 403 بشكل متطابق في كل محاولة، لذا فإن إعادة محاولتها ستستنزف ميزانية إعادة المحاولة وتجعل بيانات الاعتماد السيئة تبدو وكأنها مشكلة حد معدل. قم بالتفريع بناءً على رمز الحالة قبل منطق إعادة المحاولة، وليس بعده. هذا هو السبب الأكثر شيوعاً لـ “إعادة محاولتي لا تساعد”.
أضف عشوائية إلى التراجع. التراجع الأسي البسيط يعني أن كل عنصر متوازي تم تقييده في نفس اللحظة سيعيد محاولته في نفس اللحظة، وتعيد تشغيل الحد بخطى موحدة. جعل كل تأخير عشوائياً بشيء مثل زائد أو ناقص 30 في المائة. مع عشرة عناصر متزامنة، هذا هو الفرق بين التعافي في المحاولة الثانية والمعاناة لمدة دقيقة.
اجعل الكتابات المعاد محاولتها غير قابلة للتأثر. هذا هو الذي يفقد المال فعلاً. إذا انتهت مهلة زمنية لـ POST أو أرجعت 502، فغالباً لا تعرف ما إذا كان الخادم قد معالجها. يمكن أن تؤدي إعادة المحاولة إلى إنشاء السجل مرتين. إذا كان API يدعم مفتاح عدم القابلية للتأثر، أرسل واحداً وأعد استخدامه عبر محاولات العملية المنطقية نفسها. إذا لم يكن كذلك، تحقق من السجل قبل الكتابة في أي محاولة بعد الأولى. إعادة محاولة القراءة مجانية؛ إعادة محاولة الكتابة ليست كذلك.
شيء واحد آخر بخصوص مثالك retry_after: 30: احترم تلك القيمة بدلاً من منحنى التراجع الخاص بك عند إرسال API لها. من الجدير أيضاً معرفة أن هناك حالتين مختلفتين خلف 429، وتحتاج كل منهما إلى استجابات مختلفة. حد نافذة لكل نقطة نهاية يعني أن الحصة استنزفت حتى وقت إعادة تعيين ثابت، لذا الإصلاح الوحيد هو الانتظار وضبط معدل الطلب. تقييد خدمة عام يعني أنك ببساطة ترسل بسرعة كبيرة الآن، لذا فإن التراجع بالإضافة إلى انخفاض التزامن يوضحها. إذا كانت الاستجابة تحمل طابع زمني لإعادة التعيين، فأنت في الحالة الأولى؛ إذا كانت تحمل فقط Retry-After فأنت عادة في الحالة الثانية.