Retry Policy در ارسال پیامک؛ چگونه تلاش دوباره را بدون ارسال تکراری مدیریت کنیم؟
Retry Policy پیامک مجموعهای از قواعد برای تصمیمگیری دربارهٔ تلاش دوباره پس از خطاست: کدام خطا موقت است، چند بار میتوان تلاش کرد، بین تلاشها چقدر باید مکث کرد و چه زمانی باید متوقف شد. سیاست درست، نخست وضعیت درخواست قبلی را روشن میکند و سپس با شناسهٔ یکتا، سقف تلاش، فاصلهٔ افزایشی و ثبت نتیجه، خطر ارسال تکراری و فشار بر زیرساخت را کاهش میدهد.
فرض کنید سرویس شما درخواست ارسال رمز یکبارمصرف را به درگاه پیامک داده، اما پاسخ اتصال بهدلیل قطع لحظهای شبکه به دستتان نرسیده است. آیا پیام اصلاً پذیرفته نشده یا پذیرفته شده و تنها پاسخ آن گم شده؟ اگر بیدرنگ همان درخواست را دوباره بسازید، ممکن است کاربر دو پیام دریافت کند. از سوی دیگر، توقف کامل تلاش برای هر خطای موقت هم به از دست رفتن پیامهای ضروری میانجامد. این راهنما برای تیم فنی و عملیات توضیح میدهد چگونه میان پایداری، زمان تحویل و کنترل پیام تکراری تعادل برقرار کنند. برای دیدن جایگاه این فرایند در مسیر کامل ارسال، مقالهٔ معماری SMS Gateway سازمانی را بخوانید.
Retry Policy پیامک چیست و در کدام مرحله معنا دارد؟
در مسیر پیامک، درخواست از سامانهٔ مبدأ وارد API و صف میشود، از قواعد اعتبارسنجی و مسیریابی پیامک عبور میکند و به اتصال بالادستی سپرده میشود. خطا ممکن است در هر کدام از این لایهها رخ دهد. «تلاش دوباره» یعنی تکرار یک عملیات مشخص پس از شکست یا نامعلوم ماندن نتیجهٔ آن؛ بنابراین پیش از پیادهسازی باید روشن کنید دقیقاً کدام عملیات تکرار میشود: ثبت درخواست در API، پردازش پیام در صف یا ارسال به یک مسیر اپراتوری.
تفاوت این لایهها مهم است. اگر درخواست در اعتبارسنجی رد شده، تکرار همان دادهٔ نادرست سودی ندارد. اگر صف پیام را دوباره به پردازشگر تحویل داده، نباید یک پیام تجاری تازه ایجاد شود. اگر پاسخ اتصال بالادستی گم شده، وضعیت «نامعلوم» است و نمیتوان آن را خودکار با «ارسال نشده» برابر گرفت. به همین دلیل، یک Retry Policy قابلاتکا علاوه بر زمانبندی، به مدیریت وضعیت و شناسهٔ پایدار پیام نیاز دارد.
پاسخ کوتاه: برای هر پیام یک شناسهٔ تجاری ثابت نگه دارید؛ خطاها را به گذرا، دائمی و نامعلوم تقسیم کنید؛ تنها خطاهای مجاز را با فاصلهٔ کنترلشده تکرار کنید؛ پس از سقف تلاش یا انقضای پیام متوقف شوید؛ و نتیجهٔ هر تلاش را جدا ثبت کنید.
چه خطاهایی را باید Retry کرد و چه خطاهایی را نباید؟
همهٔ وضعیتهای «failed» یکسان نیستند. خطای گذرا از شرایطی میآید که احتمال بهبود آن در مدت کوتاه وجود دارد، مانند محدودیت موقت نرخ، قطع کوتاه اتصال یا در دسترس نبودن لحظهای سرویس وابسته. خطای دائمی تا زمانی که ورودی یا تنظیمات تغییر نکند باقی میماند، مانند شمارهٔ نامعتبر، پارامتر ناقص یا مجوز نامناسب. وضعیت سوم «نتیجهٔ نامعلوم» است: درخواست ارسال شده اما پاسخ قطعی دریافت نشده است. این وضعیت بیشترین خطر تکرار ناخواسته را دارد.
| نوع وضعیت | نمونه | رفتار پیشنهادی |
|---|---|---|
| خطای گذرا | محدودیت موقت نرخ یا قطع کوتاه اتصال | Retry با فاصله، سقف تلاش و بررسی ظرفیت مسیر |
| خطای دائمی | دادهٔ نامعتبر، مقصد نامجاز یا تنظیمات ناقص | توقف؛ ثبت علت و اصلاح داده یا پیکربندی |
| نتیجهٔ نامعلوم | Timeout پس از ارسال درخواست، بدون پاسخ قطعی | تطبیق شناسه و رویدادها؛ سپس تصمیم دربارهٔ تلاش دوباره |
| پذیرش یا ارسال تأییدشده | پاسخ موفق یا شناسهٔ بالادستی ثبت شده | ایجاد نکردن ارسال تازه؛ وضعیت تحویل را پیگیری کنید |
این جدول یک چارچوب عمومی است. معنای دقیق کدهای خطا و وضعیتها به قرارداد API، نسخهٔ پروتکل و ارائهدهنده بستگی دارد. در SMPP، پاسخ submit_sm_resp و شناسهٔ پیام از رویدادهای مربوط به پذیرش درخواست هستند؛ گزارش تحویل یا DLR رویداد بعدی است. در سامانههای REST نیز حالتهای queued، sent و delivered میتوانند جدا باشند. بنابراین رسیدن پاسخ موفق اولیه را معادل تحویل نهایی به گوشی نگیرید.
چرا Timeout حساسترین سناریو است؟
Timeout فقط میگوید پاسخ در بازهٔ انتظار شما نرسیده است. شاید عملیات در مقصد انجام شده و پاسخ در راه برگشت از دست رفته باشد. اگر در چنین وضعیتی همان عملیات اثرگذار را بدون سازوکار جلوگیری از تکرار دوباره اجرا کنید، احتمال دو بار ثبت یا ارسال وجود دارد. مستندات معماری AWS نیز برای عملیات دارای اثر جانبی، طراحی API با رفتار idempotent را توصیه میکند. این اصل در پیامرسانی باید در لایهٔ ایجاد درخواست و تا حد امکان در مسیر پردازش اعمال شود؛ صرف داشتن شمارهٔ ترتیب پروتکل، جای یک شناسهٔ تجاری پایدار را نمیگیرد.
سیاست تلاش دوباره را چگونه طراحی کنیم؟
۱. مالک تلاش دوباره را مشخص کنید
اگر برنامهٔ مبدأ، API، صف، پردازشگر و اتصال اپراتوری همگی مستقل از هم Retry کنند، یک خطا میتواند به چندین تلاش همزمان تبدیل شود. برای هر نوع خطا، یک لایه را مسئول تصمیم نهایی تعیین کنید و رفتار لایههای دیگر را در قرارداد فنی روشن بنویسید. تیم عملیات باید بداند افزایش تعداد تلاش در کدام نقطه رخ داده و کدام نقطه حق ساخت درخواست تازه دارد.
۲. یک شناسهٔ درخواست پایدار داشته باشید
برای هر رویداد کسبوکار، شناسهای یکتا تولید کنید و آن را در همهٔ تلاشها حفظ کنید. این شناسه با شناسهٔ هر تلاش یا شناسهای که ارائهدهنده پس از پذیرش میدهد متفاوت است. در ثبت داخلی، رابطهٔ «درخواست اصلی ← تلاشها ← شناسههای بالادستی ← وضعیت نهایی» را نگه دارید. هنگام دریافت دوبارهٔ همان درخواست، سامانه باید بتواند به رکورد قبلی رجوع کند؛ نوع پاسخ و مدت نگهداری این رکورد را با طول عمر پیام و نیاز عملیاتی هماهنگ کنید.
همسان بودن متن و شمارهٔ مقصد بهتنهایی معیار مطمئنی برای تکراری بودن نیست؛ ممکن است کسبوکار واقعاً بخواهد همان متن را دوباره ارسال کند. شناسهٔ مبتنی بر نیت درخواست، امکان تمایز میان «تلاش دوبارهٔ همان پیام» و «پیام جدید با محتوای یکسان» را میدهد. اگر رابط بالادستی امکان idempotency نداشته باشد، ثبت داخلی و آشتی وضعیت کمک میکند اما تضمین حذف هر نوع تکرار بیرون از مرز کنترل شما نیست.
۳. فاصلهٔ تلاشها را کنترل کنید
تکرار فوری و همزمان هزاران پیام، همان مسیر خطادار را زیر بار بیشتری میبرد. در Backoff افزایشی، فاصلهٔ تلاشهای بعدی بیشتر میشود و یک سقف زمانی دارد. افزودن Jitter یا تغییر تصادفی محدود به زمان انتظار، از همزمان شدن تلاشهای تعداد زیادی پیام جلوگیری میکند. مقدار دقیق فاصله باید با زمان حساسیت پیام، نرخ مجاز مسیر و الگوی خطا آزموده شود؛ عدد ثابت و جهانشمولی برای همهٔ سازمانها وجود ندارد.
۴. سقف تلاش و مهلت اعتبار تعریف کنید
هر پیام باید حداکثر تعداد تلاش و مهلت پایان داشته باشد. پس از رسیدن به سقف، پیام را در وضعیت قابل بررسی ثبت کنید؛ حلقهٔ بیپایان فقط صف و هزینه را بزرگتر میکند. برای پیام تراکنشی حساس، مهلت اعتبار ممکن است از سقف تلاش مهمتر باشد. رمز یکبارمصرفی که پس از انقضا تحویل شود، حتی اگر در گزارش فنی «موفق» باشد، تجربهٔ کاربر را خراب میکند. هنگام تصمیمگیری دربارهٔ Retry، زمان باقیمانده تا انقضا را هم بسنجید.
۵. نتیجهٔ نامعلوم را جدا نگه دارید
وضعیت نامعلوم نباید خودکار به صف خطای قطعی یا صف ارسال تازه منتقل شود. ابتدا با شناسهٔ درخواست، پاسخهای دیررس، رویدادهای پذیرش و گزارشهای مسیر را تطبیق دهید. اگر رابط ارائهدهنده امکان استعلام وضعیت دارد، از آن طبق قرارداد استفاده کنید. وقتی نتیجه هنوز قابل اثبات نیست، تصمیم باید تابع ارزش پیام، حساسیت به تکرار و محدودیت زمانی باشد؛ برای پیام مالی یا امنیتی، تکرار کورکورانه ممکن است از تأخیر کوتاهمدت پرهزینهتر باشد.
درخت تصمیم Retry پیامک؛ پیش از هر تلاش چه بپرسیم؟
این شش سؤال یک چکلیست مشترک برای توسعه و عملیات فراهم میکند. آن را به کد خطا و وضعیتهای واقعی سامانهٔ خود نگاشت کنید و برای هر شاخه، خروجی مشخص «تلاش دوباره»، «استعلام وضعیت»، «توقف» یا «بررسی انسانی» داشته باشید.

- پذیرش درخواست: آیا درخواست قبلی رد شده، پذیرفته شده یا نتیجهٔ آن نامعلوم است؟
- نوع خطا: آیا رفع خطا با گذر زمان محتمل است یا اصلاح داده و دسترسی لازم دارد؟
- زمان: آیا پیام هنوز برای مخاطب معتبر و مفید است؟
- بودجهٔ تلاش: آیا سقف تعداد تلاش، فاصله و محدودیت نرخ رعایت شده است؟
- هویت پیام: آیا تلاش تازه همان شناسهٔ اصلی را حفظ میکند؟
- ثبت نتیجه: آیا علت، مسیر، زمان و وضعیت هر تلاش قابل پیگیری است؟
پس از هر تغییر در قواعد، با سناریوهای واقعی و آزمایش کنترلشده رفتار سامانه را بسنجید: رد صریح درخواست، Timeout بعد از پذیرش، قطع مسیر، بازگشت پاسخ دیرهنگام، پیام منقضی و تحویل دوبارهٔ یک آیتم صف. راهنمای Queue پیامک کمک میکند اثر Retry بر عمق و عمر صف را از گلوگاههای دیگر جدا کنید.
چه شاخصهایی نشان میدهند Retry مفید است یا مشکلساز شده؟
تنها «درصد موفقیت نهایی» کافی نیست. تعداد تلاش به ازای هر پیام، نرخ خطای گذرا و دائمی، زمان از درخواست تا پذیرش، تعداد پیامهای با وضعیت نامعلوم، عمر پیامهای در صف تلاش دوباره و سهم ترافیک Retry از کل ترافیک را کنار هم ببینید. این شاخصها را به تفکیک نوع پیام، مشتری، مسیر اپراتوری و بازهٔ زمانی بررسی کنید. جهش همزمان خطا و تلاش دوباره ممکن است نشانهٔ بحران ظرفیت باشد، نه نشانهٔ اینکه باید سقف تلاش را بالاتر ببرید.
به نسبت پیامهایی که پس از Retry به وضعیت sent میرسند و آنهایی که واقعاً delivered گزارش میشوند نیز توجه کنید. موفقیت در واگذاری به مسیر بالادستی، اثبات دریافت توسط مخاطب نیست. گزارش تحویل ممکن است دیر برسد یا در بعضی مسیرها جزئیات محدودی داشته باشد. برای تحلیل، تاریخچهٔ وضعیتها را نگه دارید و از جایگزین کردن آخرین متن خطا بهجای کل زنجیرهٔ رویدادها پرهیز کنید. مقالهٔ Failover در SMS Gateway نیز مرز تلاش دوباره و تغییر مسیر هنگام اختلال را روشن میکند.
تفاوت Retry با Failover چیست؟
Retry یعنی تکرار یک عملیات پس از خطا؛ Failover یعنی انتقال کار به مسیر یا جزء جایگزین وقتی مسیر اصلی از دسترس خارج شده است. این دو میتوانند همراه باشند، اما نباید هر دو بهصورت مستقل همان پیام را ایجاد کنند. برای نمونه، پس از خطای گذرای یک مسیر ممکن است ابتدا با فاصله تلاش کنید؛ اگر پایش نشان دهد مسیر واقعاً از کار افتاده، مسیریابی درخواست بعدی یا تلاش مجاز را به مسیر دیگر ببرد. در هر دو حالت شناسهٔ اصلی، سقف تلاش و تاریخچهٔ مسیر باید ثابت و قابل ردیابی بماند.
پرسشهای رایج دربارهٔ Retry Policy پیامک
آیا هر پیامک ناموفق را باید دوباره فرستاد؟
خیر. خطاهای دائمی با تکرار همان درخواست رفع نمیشوند. ابتدا نوع خطا و مرحلهٔ شکست را مشخص کنید؛ فقط برای خطاهای مجاز و پیامهای هنوز معتبر، تلاش دوباره را فعال کنید.
آیا Timeout یعنی پیامک ارسال نشده است؟
خیر. Timeout یعنی پاسخ در زمان تعیینشده به دست شما نرسیده است. ممکن است درخواست پذیرفته شده باشد. پیش از تکرار، وضعیت را با شناسه و رویدادهای ثبتشده تطبیق دهید.
چگونه از ارسال تکراری SMS جلوگیری کنیم؟
برای هر درخواست کسبوکار شناسهٔ یکتا و پایدار تعریف کنید، همهٔ تلاشها را به همان درخواست وصل کنید، نتیجهٔ نامعلوم را جدا بررسی کنید و امکان idempotency را در لایههای تحت کنترل خود پیاده کنید. حذف کامل تکرار در مسیرهای بیرونی به قرارداد و قابلیت آن مسیر وابسته است.
Backoff چه فایدهای دارد؟
فاصلهٔ افزایشی بین تلاشها از فشار فوری بر سرویس خطادار میکاهد. Jitter نیز زمان تلاشها را پخش میکند تا همهٔ پیامهای خطادار همزمان برنگردند.
برای OTP چند بار Retry کنیم؟
عدد ثابت برای همهٔ سامانهها مناسب نیست. سقف تلاش را با زمان اعتبار رمز، محدودیت مسیر و دادهٔ واقعی تأخیر و خطا تعیین کنید؛ پس از انقضا، تلاش تازه نباید پیام بیفایدهای به کاربر برساند.
آیا Retry و Failover یک چیزند؟
خیر. Retry تلاش دوباره برای انجام عملیات است، در حالی که Failover مسیر جایگزین را وارد کار میکند. در سیاست عملیاتی باید مشخص باشد چه زمانی هرکدام اجرا میشوند و چه لایهای مسئول جلوگیری از ساخت پیام تکراری است.
سیاست Retry را در معماری کامل پیامک بررسی کنید
اگر خطاهای گذرا، صف Retry یا پیامهای تکراری به مسئلهٔ عملیاتی تبدیل شدهاند، مسیر درخواست تا اپراتور را با داده بررسی کنید. تلیرکو راهکار SMS Gateway سازمانی را برای مدیریت زیرساخت پیامکی معرفی میکند؛ جزئیات پیادهسازی باید با نیاز و معماری شما سنجیده شود.
منابع فنی: مشخصات SMPP v3.4، AWS Builders’ Library: Timeouts, retries and jitter، AWS Builders’ Library: Idempotent APIs، AWS SQS: At-least-once delivery، Twilio: Message status. این منابع اصول عمومی طراحی را توضیح میدهند و بهمعنای استفادهٔ تلیرکو از فناوری یا ارائهدهندهٔ خاص نیستند.