BroadNet
HTTP API & webhooksالموثوقية

التكافؤ وتحديد المعدّل: المفاتيح، 429، Retry-After، RateLimit

آخر تحديث 5 دقائق للقراءةقائم على المعايير
إجابة مباشرة

تجعل ترويسة Idempotency-Key (مسودّة IETF) طلبَ POST المُعاد آمنًا: يخزّن الخادم النتيجة الأولى لكل مفتاح ضمن نافذة إزالة تكرار ويعيد تشغيلها لأي تكرار، فيمنح تقديمًا مرةً واحدة بالضبط. وتحديد المعدّل يحمي الخدمة: تتلقّى الطلبات فوق الحدّ 429 Too Many Requests مع Retry-After، وتعلن ترويسات RateLimit الحصّة المتبقّية بحيث يكبح العملاء أنفسهم.

§01

ترويسة Idempotency-Key

تقديم الرسائل طلبُ POST، وهو غير متكافئ، لكن الشبكات تجبر العملاء على إعادة الإرسال حين تُفقَد استجابة — فينشأ الإرسال المزدوج الكلاسيكي. وتوحّد مسودّة Idempotency-Key من فريق عمل HTTP-API في IETF العلاجَ: يولّد العميل مفتاحًا فريدًا (‏UUID) لكل عملية منطقية ويرسله في ترويسة الطلب Idempotency-Key. ويسجّل الخادم المفتاح مع نتيجة الطلب الأول، وإن رأى المفتاح نفسه ثانيةً لا ينفّذ مرةً ثانية — بل يعيد النتيجة المخزّنة. فإعادة الإرسال بعد انتهاء مهلة مضمونة الأمان: إمّا لم يصل الطلب الأول قطّ (فينفّذ هذا) أو وصل (فتُعاد نتيجته). والمفتاح يخصّ العملية لا الاتصال، فيعيد العميل استخدام المفتاح نفسه عبر كل إعادة إرسال لتلك العملية.

طلب POST متكافئ بمفتاح يولّده العميلhttp
# Generic IETF-draft example (not the BroadNet API, which takes no
# Idempotency-Key header: see /developers/idempotency)
POST /v1/messages HTTP/1.1
Host: api.example
Idempotency-Key: 8f14e45f-ea7b-4c0f-9b2a-1d2c3e4f5a6b
Content-Type: application/json

{ "to": "+15551234567", "text": "..." }

# first call  -> 202 Accepted, id 01HZY8Q3M6   (executed, stored)
# same key    -> 202 Accepted, id 01HZY8Q3M6   (replayed, not re-sent)
§02

نافذة إزالة التكرار وإعادة تشغيل الاستجابة والتعارضات

مفتاح التكافؤ لا يُتذكَّر إلى الأبد؛ يحتفظ به الخادم لنافذة إزالة تكرار (24 ساعة عادةً) طويلة بما يكفي لتغطية أي إعادة إرسال واقعية، ثم تنتهي. وضمن تلك النافذة يعيد تكرارُ المفتاح تشغيلَ رمز الحالة والجسم المخزّنين حرفيًا — الـ 202 نفسه ومعرّف الرسالة نفسه — بحيث يرى العميل بالضبط ما كان سيراه لو وصلت الاستجابة الأولى. وحالتان طرفيّتان تحتاجان معالجة صريحة. فإن أُعيد استخدام مفتاح بجسم طلب مختلف، فذلك خلل عميل ويعيد الخادم 409 Conflict بدل إرسال الشيء الخطأ بصمت. وإن وصلت إعادة إرسال بينما الطلب الأول لا يزال قيد التنفيذ، يعيد الخادم تعارضًا أو «قيد التقدّم» بدل بدء تنفيذ ثانٍ، فلا يستطيع التزامنُ هزمَ الضمان.

نتائج Idempotency-Key
الحالةسلوك الخادمالحالة
مفتاح جديدنفّذ، ثم احفظ المفتاح والنتيجةعادي (مثلاً 202)
تكرار المفتاح، المتن نفسهأعِد الاستجابة المخزّنة، ولا تُعِد التنفيذالحالة الأصلية
تكرار المفتاح، متن مختلفرفض — المفتاح مرتبط بالحمولة الأولى409 Conflict
تكرار أثناء معالجة الطلب الأوللا تبدأ تنفيذًا ثانيًا409 / قيد التنفيذ
انتهت صلاحية المفتاح (بعد انقضاء النافذة)يُعامل كجديدعادي
§03

تحديد المعدّل و429

تحمي منصّة المراسلة المشتركة نفسها ومستأجريها الآخرين بتقييد سرعة نداء أي عميل، وتشير إلى تجاوز بحالة محدّدة. ويُعرّف RFC 9110 وRFC 6585 رمز 429 Too Many Requests لهذا بالضبط: أرسل العميل طلبات كثيرة جدًا في مدة معيّنة. والخادم الحَسَن السلوك يقرن 429 بترويسة Retry-After تخبر العميل كم ينتظر قبل المحاولة ثانيةً (إمّا تأخير بالثواني أو تاريخ HTTP). والتزام العميل احترامُها — يتوقّف، وينتظر الفترة المشار إليها، ثم يستأنف — بدل إعادة الإرسال فورًا، مما يعمّق الحِمل الزائد فحسب. والـ 429 عابر وآمن إعادة إرساله، بخلاف 4xx التي تدلّ على طلب مشوّه.

429 مع ترويستي Retry-After وRateLimithttp
HTTP/1.1 429 Too Many Requests
Retry-After: 2
RateLimit: limit=100, remaining=0, reset=2
RateLimit-Policy: 100;w=1
Content-Type: application/problem+json

{ "type": "https://example/problems/rate-limited",
  "title": "Too Many Requests", "status": 429 }
§04

ترويستا RateLimit وRateLimit-Policy

التفاعل مع 429 بعد وقوعها إهدار؛ ومسودّة ترويسات RateLimit من IETF تتيح للعميل رؤية ميزانيته قبل تجاوزها. فعلى الاستجابات الاعتيادية يعلن الخادم الحصّة الراهنة بترويسة RateLimit تحمل الحدّ والمخصَّص المتبقّي والثواني حتى إعادة ضبط النافذة، وترويسة RateLimit-Policy تصف السياسة نفسها (مثلًا 100 طلب لكل نافذة ثانية واحدة). والعميل الذي يقرأ هذه يستطيع ضبط وتيرته — يبطئ كلّما اقترب المتبقّي من الصفر — ولا يُطلِق 429 البتّة. وهذا يحوّل تحديد المعدّل من رفض عقابي بعد الوقوع إلى إشارة تعاونية، وهو غاية توحيد أسماء الترويسات بحيث تستهلكها أي مكتبة عميل.

ترويسات الإشارة القياسية لتحديد المعدّل
الترويسةينقلمثال
429 Too Many Requestsحالة تجاوز الحد المسموح بهسطر الحالة
Retry-Afterكم من الوقت يجب الانتظار قبل إعادة المحاولةRetry-After: 2
RateLimitالحد / المتبقي / إعادة التعيين للنافذةlimit=100, remaining=17, reset=1
RateLimit-Policyسياسة الحصص المعمول بها100;w=1 (100 per 1s)
§05

دلو الرموز وكيفية فرض الحدود

خوارزمية دلو الرموز هي الآليّة المعتادة خلف هذه الترويسات لأنها تقيّد المعدّل المستدام مع احتمال دفعات قصيرة. فالدلو يحمل عددًا ثابتًا أقصى من الرموز ويعاد ملؤه بمعدّل مطّرد؛ ويزيل كل طلب رمزًا، والطلب الذي يجد الدلو فارغًا يُرفَض بـ 429. وحجم الدلو يحدّد الدفعة التي يستطيع العميل إنفاقها دفعة واحدة، ومعدّل إعادة الملء يحدّد السقف طويل الأمد، فيستطيع العميل إرسال دفعة سريعة بعد فترة خمول لكنه لا يتجاوز المتوسّط. وقيمة remaining في RateLimit هي فعليًا عدد الرموز، وreset هو موعد اكتمال ملء الدلو — وهي بالضبط المعلومة التي يحتاجها عميلٌ مضبوط الوتيرة. وهذا التحكّم في التدفّق عند طبقة HTTP هو نظير REST لتحجيم نافذة SMPP وكبح enquire_link على الجلسة الثنائية.

§06

الضغط العكسي من العميل

نصف السلوك الجيّد تجاه تحديد المعدّل من جانب العميل هو الضغط العكسي: تشكيل الحِمل الصادر بحيث يبقى ضمن الميزانية المعلَنة بدل إطلاق كل شيء وامتصاص 429. وعمليًا يعني ذلك مُحدِّدًا من جانب العميل (دلو رموز يحاكي الخادم)، وقراءةَ ترويسات RateLimit لضبط الوتيرة، وعند 429 التوقّفَ لفترة Retry-After مع تشويش زمني قبل الاستئناف. ولإرسال جماعي يعني هذا قِسمة التقديمات إلى السقف المستدام بدل إغراقها، فتبقى المنصّة سليمة ويبقى زمن استجابة العميل نفسه متوقَّعًا. وتوثّق BroadNet سلوك التكافؤ وتحديد المعدّل الفعلي لديها للمطوّرين.

التعليمات

الأسئلة المتكررة

ماذا تفعل ترويسة Idempotency-Key؟

تجعل طلب POST المُعاد آمنًا. يرسل العميل مفتاحًا فريدًا لكل عملية منطقية؛ وينفّذ الخادم الطلب الأول بذلك المفتاح ويخزّن النتيجة، ثم يعيد تشغيل النتيجة المخزّنة لأي تكرار للمفتاح نفسه ضمن نافذة إزالة تكرار. فإعادة الإرسال بعد استجابة مفقودة إمّا تنفّذ مرة واحدة أو تعيد التشغيل — دون إرسال مزدوج أبدًا. وهي محدَّدة في مسودّة فريق عمل HTTP-API في IETF.

كم يتذكّر الخادم مفتاح التكافؤ؟

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

ماذا يحدث إن أعدت استخدام مفتاح تكافؤ بجسم مختلف؟

يرفضه الخادم بـ 409 Conflict. فالمفتاح مربوط بحمولة الطلب الأول، لذا إعادة استخدامه بجسم مختلف تُعامَل معاملة خطأ عميل بدل إرسال الرسالة الخطأ بصمت. أعِد استخدام المفتاح نفسه لإعادات إرسال العملية المطابقة فقط.

ماذا ينبغي أن يفعل العميل حين يتلقّى 429؟

يتوقّف ويحترم ترويسة Retry-After — ينتظر الثواني المشار إليها (أو حتى التاريخ المعطى)، ثم يستأنف — بدل إعادة الإرسال فورًا، مما يعمّق الحِمل الزائد فحسب. والـ 429 عابر وآمن إعادة إرساله بعد انقضاء الانتظار، ويُفضَّل بتشويش زمني طفيف بحيث لا يستأنف عملاء كثيرون في تزامن تامّ.

لماذا ترويستا RateLimit وRateLimit-Policy؟

تتيحان للعميل رؤية حصّته قبل تجاوزها. فـ RateLimit تحمل الحدّ والمخصَّص المتبقّي وموعد إعادة الضبط للنافذة الراهنة؛ وRateLimit-Policy تصف السياسة (مثلًا 100 طلب في الثانية). والعميل الذي يقرأهما يستطيع ضبط وتيرته وتجنّب إطلاق 429 البتّة. وكلتاهما محدَّدتان في مسودّة IETF.

كيف يرتبط دلو الرموز بترويسات RateLimit؟

دلو الرموز هو آليّة الفرض: دلوٌ بحجم ثابت يعاد ملؤه بمعدّل مطّرد، وينفق كل طلب رمزًا، ودلوٌ فارغ يعطي 429. وقيمة remaining في RateLimit هي جوهريًا عدد الرموز الراهن، وreset هو موعد إعادة ملء الدلو — فالعميل القارئ لتلك الترويسات يعرف بالضبط كم بقي لديه من دفعة ومعدّل مستدام.

مراجع

مواصفات المصدر

تستند هذه الصفحة إلى المعايير المنشورة. يفتح في علامة تبويب جديدة.

BNتتم صيانته بواسطة فريق الهندسة BroadNet·خدمة الرسائل عالية الجودة منذ عام 2003
ضعه على السلك

قم بالبناء باستخدام ربط SMPP حقيقي وواجهة برمجة تطبيقات REST.

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