توسع N8N الأفقي

وصف المشكلة/الخطأ/السؤال

نحن نبحث عن إرشادات بشأن تزامن عامل n8n Queue Mode والتوسع الأفقي.

حمل العمل المتوقع لدينا حول 1,000 مستخدم متزامن، ونحن نخطط لتوسيع عمال n8n الخاصين بنا أفقياً.

حالياً، نقوم بتشغيل عمال n8n على مثيلات AWS EC2 من نوع t3a.medium. نحن لا نستخدم AWS Fargate.

إعدادنا الحالي هو:

  • 1 عامل

  • التزامن: 50

  • المعالج: 1 vCPU

  • الذاكرة: 1.5 GB

  • قاعدة البيانات: PostgreSQL

  • نظام التشغيل: Amazon Linux

  • وضع التنفيذ: Queue Mode

نود أن نفهم:

  • ما هو التزامن الموصى به لكل عامل لهذا النوع من حمل العمل؟

  • هل التزامن 50 مرتفع جداً لمثيل t3a.medium مع 1 vCPU و 1.5 GB RAM؟

  • كيف يجب أن نحدد التزامن الأمثل بناءً على المعالج والذاكرة؟

  • كيف نحدد عدد العمال الأمثل؟

  • كيف يجب أن نراقب عمق الطابور واستخدامه كإشارة للتوسع الأفقي؟

  • ما هي المقاييس التي يجب أن نستخدمها للتوسع — عمق الطابور أو المعالج أو الذاكرة أو زمن تنفيذ التنفيذ أو مزيج منها؟

  • هل هناك نهج موصى به للتوسع التلقائي لعمال EC2 بناءً على عمق الطابور؟

  • ما هي أفضل طريقة لـ اختبار الحمل لهذا الإعداد وتحديد التزامن/عدد العمال الأمثل؟

على سبيل المثال، إذا قمنا في النهاية بالتوسع إلى:

10 عمال من نوع t3a.medium

كيف يجب أن نحدد ما إذا كان يجب أن يكون لكل عامل تزامن قدره 5 أو 10 أو 20 أو 50 وما إلى ذلك؟

نود أن نحصل على أي توصيات أو خبرة من الواقع مع n8n Queue Mode + PostgreSQL + عمال EC2 موسعين أفقياً.

ما هي رسالة الخطأ (إن وجدت)؟

لا توجد رسالة خطأ محددة. هذا بشكل أساسي سؤال تخطيط السعة والتوسع الأفقي.

يرجى مشاركة سير العمل الخاص بك

غير قابل للتطبيق — هذا سؤال بنية تحتية/عامل توسع بدلاً من مشكلة سير عمل محددة.

شارك الناتج الذي أرجعته آخر عقدة

غير قابل للتطبيق.

مرحباً @Yash_Nerkar، بينما تنتظر ردّاً، إليك بعض الأشياء التي قد تساعدك:

الموارد المقترحة

تم مطابقتها تلقائياً مع سؤالك.

المستندات:

المنتدى:

@jcuypers، @anon45958619، @hubschrauber - لقد ساعدتم في حل مشاكل مماثلة من قبل، هل يمكنكم إلقاء نظرة؟

تم الاقتراح تلقائياً بواسطة روبوت مجتمع n8n. إنه نسخة تجريبية - يرجى مشاركة ملاحظاتك هنا.

مرحباً @Yash_Nerkar

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

  1. التزامن 50 على 1 vCPU و1.5 GB عالٍ جداً. العامل هو عملية Node واحدة مع حلقة حدث واحدة، لذا فإن 50 يعمل فقط عندما تقضي التنفيذات وقتها في الانتظار على HTTP أو قاعدة البيانات. أي تحويل json يتسلسل على النواة الواحدة، والذاكرة عادة ما تكون حد التقيد: تنفيذات أثناء الطيران مضروبة في حجم البيانات p95 الخاص بك يجب أن تناسب 1.5 GB. القيمة الافتراضية هي 10 لسبب ما، والذهاب تحت 5 ينشط تحذير من العامل نفسه.
  2. حددها من خلال القياس، وليس الصيغة: حمّل عاملاً واحداً بتزامن ثابت مع سير عملك الفعلي، ارفعه حتى يتدهور زمن كمون p95 أو تقترب الذاكرة من الحد الأقصى، والهضبة هي رقمك لكل عامل. عدد العمال هو ثم التنفيذات أثناء الطيران مقسومة على ذلك، بالإضافة إلى مساحة احتياطية.
  3. بالنسبة لإشارة القياس، اضبط N8N_METRICS_INCLUDE_QUEUE_METRICS=true على المثيل الرئيسي واكشط /metrics. n8n_scaling_mode_queue_jobs_waiting هو عمق الطابور الخاص بك: القيمة غير صفرية المستمرة تعني أن العمال مشبعون، وهي أنظف إشارة تلقائية للقياس لديك. ادفعها إلى CloudWatch كمقياس مخصص وقيّم ASG منها، وتوسع للداخل فقط عندما تكون صفراً لفترة من الوقت. وحدة المعالجة المركزية والذاكرة هي أنذارات صحية لكل عامل، وليست إشارة القياس.
  4. فخ EC2 واحد لاختبار الحمل: t3a قابلة للانفجار. يظهر تشغيل الاختبار على رصيد وحدة المعالجة المركزية الجديد أداءً لا يمكن للمثيل الحفاظ عليها، لأنها تقيد إلى الخط الأساسي بمجرد استنزاف الأرصدة. إما أن تختبر لفترة طويلة بما يكفي لاستنزافها أو استخدم فئة غير قابلة للانفجار للعمال الذين تخطط لتشغيلهم بكثافة.

إذا قمت بالتوسع إلى 10 عمال، فلا تستخدم التزامن الافتراضي بقيمة 50. استخدم هذا المنطق:

شكراً على الشرح المفصل. دعني أضيف بعض السياق حول سير العمل الفعلي لدينا.

عادةً ما يتضمن كل تنفيذ n8n:

  • حوالي 10 استدعاءات OpenAI API

  • عدة استدعاءات قاعدة بيانات

  • بعض سير العمل الفرعية

  • معالجة قليلة جداً تتطلب موارد CPU

لذا فإن متوسط وقت التنفيذ البالغ حوالي 20 ثانية يُقضى في الغالب في الانتظار للخدمات الخارجية (OpenAI APIs / قاعدة البيانات) بدلاً من القيام بعمل يتطلب موارد CPU.

nتستخدام CPU لدينا منخفضة بشكل عام نسبياً، ونحن ندرس استخدام تزامن عامل أعلى للحفاظ على انشغال العمال أثناء انتظار التنفيذات للعمليات I/O.

حركة المرور المتوقعة لدينا يمكن أن تصل إلى حوالي 200-300 مستخدم/ثانية.

هنا أحاول فهم المقارنة بين التزامن والانتظار في الطابور.

على سبيل المثال، لنفترض أن لدينا عامل يحتوي على:

Concurrency = 20

وفجأة نستقبل 100 تنفيذ.

فهمي تقريباً كالتالي:

100 تنفيذ وارد
        ↓
20 يبدأان التنفيذ
        ↓
80 تبقى في انتظار طابور Redis
        ↓
عندما ينتهي التنفيذ
        ↓
يتم اختيار التنفيذات التالية

بما أن متوسط التنفيذ يستغرق حوالي 20 ثانية، ألن يزيد التزامن المنخفض بشكل كبير من وقت انتظار الطابور؟

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

لذا أحاول فهم كيفية تحقيق التوازن بين:

تزامن العامل مقابل وقت انتظار الطابور مقابل عدد العمال

على سبيل المثال، هل شيء مثل هذا منطقي؟

الخيار أ
10 عمال × تزامن 20
= 200 تنفيذ متزامن

الخيار ب
10 عمال × تزامن 50
= 500 تنفيذ متزامن

بما أن معظم وقت سير العمل لدينا يُقضى في الانتظار لـ OpenAI/DB بدلاً من CPU، هل التزامن الأعلى (مثل 50) معقول فعلاً، بافتراض بقاء الذاكرة ضمن حدود آمنة؟

أم أن هناك طريقة أفضل لتحديد التزامن الأمثل بشكل تجريبي؟

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

أود بشكل خاص بعض التوجيهات حول كيفية قياس هذا لسير العمل الذي يعتمد بشكل أساسي على العمليات المرتبطة بـ I/O.

مرحبا @Yash_Nerkar

قم بحساب رياضيات الصفوف قبل الاختيار بين A و B: الفتحات المطلوبة = معدل الوصول × المدة. عند 200 إلى 300 عملية تنفيذ في الثانية و 20 ثانية لكل منها، هذا يعني 4000 إلى 6000 عملية تنفيذ متزامنة، لذا فإن 200 و 500 فتحة كلاهما أقل من المطلوب بمقدار رتبة واحدة والتراكم ينمو بلا حد. إذا كان 200 إلى 300 في الثانية مستخدمين وليس عمليات تنفيذ، قم بقياس عمليات التنفيذ الفعلية في الثانية أولاً، وكل رقم آخر ينتج عنه. حالة الذروة الخاصة بك جيدة على أي حال: 100 وصول مقابل 200 فتحة حرة جميعها تبدأ على الفور، وانتظار الصف يظهر فقط عندما يقترب معدل × المدة من إجمالي الفتحات.

للعمل المرتبط بـ I/O، الإنتاجية المتزامنة الأعلى لكل عامل معقولة ضمن سقفين: الذاكرة (قيد التنفيذ × حمولة p95 يجب أن تتسع) ونطاق التأثير (واحد OOM عند التزامن 50 يقتل 50 عملية تنفيذ). أصلح إجمالي الفتحات أولاً، ثم اقسمها على قدرة العامل الفعلية المقاسة للحصول على عدد العمال، وقم بالتوسع على n8n_scaling_mode_queue_jobs_waiting البقاء غير صفر. شيء واحد سيعضك في هذا النطاق: آلاف استدعاءات OpenAI المتزامنة تصل إلى حدود معدل OpenAI قبل n8n، و 429 محاولات إعادة تمتد بصمت لمدة 20 ثانية الخاصة بك، لذا قم بالتحديد الحجم مقابل طبقة OpenAI أيضاً.

لتحمل 300 طلب/ثانية بمتوسط وقت تنفيذ 20 ثانية، تحتاج إلى “السعة الإجمالية” تقريباً 6000 تنفيذ متزامن

على t3a.medium (1.5 غيغابايت ذاكرة الوصول العشوائي)، ستكون محدوداً بالذاكرة قبل أن تصل إلى 6000. لنفترض أنه يمكنك دفع التزامن بأمان إلى 50 لكل عامل.

حساب التوسع الأفقي:

  • السعة المستهدفة: 6000
  • أقصى تزامن لكل عامل: 50
  • عدد العمال المطلوبين: 6000 / 50 = 120

شكراً، هذا منطقي. أجريت اختبار حمل على إعدادنا الحالية، وأردت مشاركة النتائج لأنها تبدو مختلفة تماماً عن حساب التنفيذ المتزامن النظري البالغ 6000.

الإعداد الحالي:

  • 1 × t3a.medium

  • 1 vCPU

  • 1.5 GB RAM

  • n8n Queue Mode

  • Worker concurrency: 50

  • PostgreSQL

  • سير العمل يحتوي على ~10 استدعاءات OpenAI + استدعاءات قاعدة البيانات + سير عمل فرعي

  • متوسط وقت التنفيذ حوالي 20 ثانية

للاختبار، لا نريد فعلياً تشغيل جميع استدعاءات OpenAI وعمليات قاعدة البيانات بشكل متكرر، حيث سيستهلك ذلك قدراً كبيراً من أرصدة OpenAI ويفرض حملاً غير ضروري على قاعدة البيانات الخاصة بنا.

لذا، في سير عمل الاختبار، استبدلنا تلك الاستدعاءات الخارجية بـ عقد Wait تحاكي تقريباً نفس مقدار الوقت المستغرق في الانتظار لطلبات OpenAI/قاعدة البيانات. هذا يسمح لنا بإعادة إنتاج نمط تنفيذ انتظار I/O مشابه دون الحاجة إلى الاستدعاءات الخارجية الفعلية.

أجريت اختبار k6 مع 50 VUs متزامنة، يقوم كل VU بطلب واحد.

النتائج:

  • 50 طلب إجمالي

  • 47 ناجح

  • 3 فشل/انقطاع → معدل فشل 6%

  • متوسط مدة HTTP: 35.48s

  • الوسيط: 35.98s

  • p95: 39.86s

  • الحد الأقصى: 39.88s

  • مدة سير عمل n8n: ~35.6s في المتوسط

من المثير للاهتمام أنه عند النظر إلى التنفيذات مباشرة في واجهة n8n، كان التنفيذ الأول حوالي 21s والأخير حوالي 29s.

لذا حتى مع 50 طلب متزامن فقط، نشهد بالفعل زيادة كبيرة في الكمون وعدد قليل من حالات انقطاع الاتصال.

هذا يجعلني متردداً في افتراض ببساطة أن concurrency=50 يعني أن جهاز t3a.medium واحد يمكنه توفير 50 فتحة تنفيذ مفيدة بأمان.

بما أن سير العمل الفعلي الخاص بنا يعتمد في الأساس على I/O (استدعاءات OpenAI + قاعدة البيانات) بدلاً من استهلاك CPU كثيفاً، أحاول فهم ما الذي قد يفسر هذا السلوك.

نتائجك تثبت أن ما يعمل على الورق (التزامن العالي) لا يعمل في الممارسة العملية على هذا البنية التحتية المحددة، حتى بالنسبة لأعباء العمل المرتبطة بالإدخال والإخراج.

لقد حددت تجاربك بشكل صحيح أن 1.5 جيجابايت من ذاكرة الوصول العشوائي مدمجة مع التوازي العالي هي نقطة الاختناق، وليس المعالج. لا تزيد التزامن على الحالات الأصغر؛ بدلاً من ذلك، قم بالتوسع الأفقي بإضافة عمال إضافيين بتزامن أقل (على سبيل المثال، عاملان × 20 تزامن).

لا، الطلب لم يفشل. إنه مجرد انتهاء مهلة الاستجابة لأننا حددنا 30 ثانية كمهلة زمنية.

{“output”:“حسناً. سأتحقق من ذلك.”}

مرحبا @Yash_Nerkar
المنشور 11 يحرك الهدف. نجح العمل وتخلى العميل عند 30 ثانية، لذا ما يضغط عليه حملك فعليًا أولاً هو اتصالات HTTP المفتوحة، وليس فتحات العامل. في وضع قائمة الانتظار، يقوم العامل بتنفيذ التنفيذ بينما يبقى العميل متصلاً بالمثيل الرئيسي أو webhook طوال المدة، لذا من 200 إلى 300 في الثانية لمدة 20 ثانية لكل منها يعني أن هذه الطبقة تحتفظ بـ 4,000 إلى 6,000 مقبس مفتوح، واليوم إنها عملية واحدة في نفس الصندوق مثل العامل.
مهلة انتظار عميل مدتها 30 ثانية مقابل متوسط 20 ثانية تفشل أيضًا في الذيل مهما أضفت من عمال، وكل واحد من تلك الطلبات لا يزال ينفق 10 استدعاءات OpenAI، لذا تدفع مقابل ردود لا يتلقاها أحد.
توقف عن الاحتفاظ بالاتصال. عيّن خاصية “Respond to Immediately” الخاصة بعقدة Webhook، والتي تُرجع “تم بدء سير العمل” بمجرد إدراج الوظيفة في قائمة الانتظار، ثم قم بتسليم النتيجة من خلال رد نداء أو نقطة نهاية حالة يستقصيها العميل. توقفات انتظار الطلب تتوقف عن كونها سؤالاً متعلقاً بالقدرة وعمق قائمة الانتظار يصبح الشيء الوحيد الذي تقيسه.
إذا كان يجب أن يبقى عقد API متزامناً، قسّم تلك الطبقة: قم بتشغيل عمليات n8n webhook خلف موازن التحميل، أبقِ العملية الرئيسية خارج المجموعة، وحجّمها حسب الاتصالات المتزامنة وليس وحدة المعالجة المركزية.

شكراً، هذا يوضح سؤال الهندسة المعمارية بشكل أفضل بكثير.

أعدنا تشغيل نفس الاختبار باستخدام سير العمل القائم على Wait-node لتجنب استهلاك رصيد OpenAI أو فرض حمل غير ضروري على PostgreSQL.

مع 50 VUs، كانت نتائج k6:

  • 50 طلب
  • 100% HTTP 200
  • 0% فشل
  • HTTP p95: 4.85s
  • Workflow p95: ~4.97s

إذاً اختبار بدون الاحتفاظ بالاتصال يتصرف بشكل جيد.

ومع ذلك، عندما أنظر إلى عمليات n8n الفعلية، يزيد وقت التنفيذ تحت الحمل — التنفيذات الأولى حول 20s، بينما قد تصل الحقيقة لاحقاً إلى ~28s. لذا أعتقد أن هناك تنافساً/صفاً ما زال يحدث حتى وإن كان سير العمل المحاكى ينتظر في الغالب.

بخصوص الهندسة المعمارية، خطتنا الحالية هي الاحتفاظ بـ instance n8n الرئيسي على EC2 مخصص ولدينا فقط instances العامل في مجموعة التوسع التلقائي، مع استخدام Redis للتعامل مع الطابور. شيء مثل:


                  Load Balancer
                       |
                       v
                 Main EC2
                n8n main/webhook
                       |
                       v
                     Redis
                       |
          +------------+------------+
          |            |            |
          v            v            v
       Worker 1     Worker 2     Worker 3
          \            |            /
           +-----------+-----------+
                       |
                       v
                  PostgreSQL

هل هذا الفصل منطقي؟

فكري هو أن EC2 الرئيسي يجب أن يبقى مستقراً نسبياً، بينما العمال هم ما نوسعه أفقياً بناءً على عمق الطابور/الحمل.

يمكننا أيضاً تغيير webhook للرد فوراً والتعامل مع نتيجة سير العمل من خلال callback من جانبنا، بحيث لا نبقي اتصال HTTP مفتوحاً لمدة 20-28 ثانية كاملة.

شيء واحد لا أزال مرتبكًا تمامًا بشأنه هو استراتيجية توسيع العمال الفعلية:

هل يجب أن نستمر في توسيع العمال بناءً بشكل أساسي على عمق الطابور؟ وما الذي سيكون معقولًا من حيث التزامن لكل عامل — شيء مثل 20 عملية تنفيذ لكل عامل، أم يجب أن نكون أقرب إلى 50–100؟
تذكر وثائق n8n تقريبًا 100–200 ميجابايت من الذاكرة لكل عملية تنفيذ متزامنة، لكنني لست متأكدًا من كيفية ترجمة ذلك إلى حجم EC2 الصحيح وإعداد التزامن لعبء العمل الخاص بنا.

على سبيل المثال، إذا قللت التزامن إلى 20 لكل عامل، ألن ينمو طابور Redis بسرعة أكبر بكثير، مما يعني أنه سيتعين علينا الاستمرار في إضافة المزيد من الخوادم؟ من ناحية أخرى، إذا حافظنا على التزامن حول 50–100 واستخدمنا حالات بها المزيد من الذاكرة/وحدة المعالجة المركزية، هل هذا نهج أفضل؟

لذا أحاول أن أفهم التوازن الصحيح بين:

  • التزامن لكل عامل
  • الذاكرة/وحدة المعالجة المركزية لكل عامل
  • عدد العمال
  • عمق طابور Redis / عتبة التوسيع

اعتذر عن أسئلتي الغبية — لا أزال أتعلم كيفية عمل ASG والتوسيع الأفقي، لذا أحاول أن أفهم الطريقة الصحيحة للتفكير في هذا بدلاً من مجرد إضافة المزيد من EC2s للمشكلة.

إن p95 الخاص بك البالغ 4.85 ثانية هو الآن الوقت المستغرق للقبول والإدراج في الطابور، وليس الوقت المستغرق لتشغيل سير العمل. التنفيذات لا تزال تستغرق 20 إلى 28 ثانية، لذا لم تتحسن السعة الاستيعابية للعامل بين الاختبارين، لقد توقفت عن قياسها من k6. صعود 20 إلى 28 هو إشارة السعة الخاصة بك، والرقم HTTP الآن يخبرك فقط أن المثيل الرئيسي يواكب الوضع.
تحت هذا الصعود يوجد شيء لم تلمسه بعد. DB_POSTGRESDB_POOL_SIZE يفترضه افتراضياً إلى 2، لذلك يفتح كل عامل اتصالي Postgres بغض النظر عن التزامن الذي تعينه. عند التزامن 50 يدفع تلك التنفيذات الخمسون عمليات الكتابة الخاصة بهم عبر اتصالين والتنفيذات اللاحقة تنتظر. رفعه مع التزامن وراقب Postgres max_connections، لأن إجمالك هو العمال مضروباً في حجم المجموعة:

DB_POSTGRESDB_POOL_SIZE=12

نعم. الفجوة هي أن مثيل واحد رئيسي هو نقطة فشل واحدة، وتشغيل مثيل ثان يتطلب متعدد-رئيسي، وهو متاح فقط في Enterprise.

لا. عمق الطابور يتبع إجمالي الفتحات، وهي العمال مضروبة في التزامن، لذا 10 عمال بـ 20 و4 عمال بـ 50 كلاهما يعطي 200 فتحة وطابور بنفس الحجم. التزامن يقرر فقط كيفية حزم تلك الفتحات على الأجهزة.

أي التزامن يحافظ عليه عامل واحد بمجرد مطابقة مجموعته به. اشتر عدد الفتحات باستخدام عدد العمال بعد ذلك، لأن حزم الفتحات بشكل أكثر كثافة يكلف نطاق الانفجار، موت عامل واحد عند التزامن 50 يأخذ معه 50 تنفيذاً.

لا تنشر n8n هذا الرقم، وليس هناك رقم عام موجود، لأنه حجم الحمولة الخاصة بك لكل تنفيذ قيد الرحلة. قسه: قم بتشغيل عامل واحد بتزامن ثابت وراقب RSS.

فيما يتعلق بوقت التنفيذ 20–28 ثانية، هل يجب أن نصلح أولاً حجم مجموعة PostgreSQL والقياس مرة أخرى قبل اتخاذ أي قرارات بشأن تزامن العامل؟

نعم. أي رقم لكل عامل تقيسه مقابل مجموعة من 2 هو قياس للمجموعة وليس للعامل، وكل من عدد العمال والحد الأدنى للتوسع التلقائي مشتق من هذا الرقم، لذا ينتشر الخطأ في كل قرار بعده.
أعطِ إعادة التشغيل حمولة واقعية رغم ذلك. تحمل المجموعة بيانات التنفيذ، لذا فإن سير العمل الذي يتكون من عقد الانتظار لا يكتب شيئاً تقريباً ولن يظهر تأثير التغيير الذي أجريته للتو. عقدة Code تصدر JSON بحجم استجابة OpenAI النموذجية تعيد حجم الكتابة دون إنفاق أرصدة.
إذا كان لا يزال بطيئاً بعد ذلك، فإن نفس الاختناق يحتوي على رافعة ثانية. EXECUTIONS_DATA_SAVE_ON_SUCCESS يأخذ القيمة الافتراضية all، لذا فإن كل عملية تنفيذ ناجحة تكتب بيانات كاملة عبر تلك المجموعة:

EXECUTIONS_DATA_SAVE_ON_SUCCESS=none

هذا يقلل من الذي يمر عبر المجموعة بدلاً من توسيعها، والإخفاقات لا تزال يتم حفظها لأغراض تصحيح الأخطاء.

اقتراح أنشول EXECUTIONS_DATA_SAVE_ON_SUCCESS=none صحيح لمشكلة ضغط المجموعة، والتحفظ بأن الأخطاء لا تزال يتم حفظها يغطيك في الأخطاء الشديدة. الفجوة التي يفتحها أكثر ليونة من الفشل: عند مستوى حجمك، فشل OpenAI 429s وإعادة المحاولات (لوبيز أشار إلى هذا في المنشور 6) لا يظهران دائماً كتنفيذ فاشل، أحياناً إعادة محاولة أو متابعة على مسار الفشل يعودان بتشغيل ناجح من الناحية التقنية مع إكمال مقطوع أو فارغ. بمجرد أن يتوقف حفظ بيانات النجاح، لا يترك هذا التشغيل أي أثر للقبض عليه بعد الواقعة، ستلاحظ فقط في المصب عندما ينكسر شيء ما مبني على هذا الناتج لاحقاً..

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

سعيد بالدخول في مزيد من التفاصيل حول كيفية تنظيمنا لذلك إذا كان مفيداً.