TGViewer
C# Geeks (.NET) C# Geeks (.NET) @csharpgeeks · 550 subscribers
Post #828 207
ءPriority به‌تنهایی کافی نیست؛ Provider هم محدودیت دارد

فرض کن Queue ما آماده است، اما SMS Provider فقط اجازه می‌دهد:
100 پیامک در ثانیه

ارسال کنیم.
اگر Dispatcher با سرعت ۱۰ هزار پیامک در ثانیه به Provider درخواست بفرستد، اتفاق‌های بدی رخ می‌دهد:
خطای Rate Limit ،Timeout،Retry زیاد ،فشار روی شبکه ،افزایش Backlog و در نهایت Retry Storm
پس بعد از Priority Queue به یک Rate Limiter نیاز داریم:
ءRate Limiter باید ظرفیت واقعی Provider را رعایت کند.
برای مثال:
Provider Limit:
100 SMS/sec

Dispatcher:
بیشتر از 100 ارسال در ثانیه انجام ندهد

اما اگر OTP در صف باشد، نباید با افزایش Priority، محدودیت Provider را دور بزنیم. Priority یعنی:
این پیام زودتر انتخاب شود.

نه اینکه:
این پیام بدون توجه به ظرفیت Provider ارسال شود.


🔁 ءRetry را داخل همان صف اصلی نریزیم
فرض کن ارسال یک پیامک شکست می‌خورد.
راه ساده اما خطرناک:
Send Failed
↓
Put back into Main Queue

اگر Provider مشکل داشته باشد، پیام دائماً از Queue خارج و دوباره وارد آن می‌شود.
راه بهتر، داشتن Retry Policy است:
Attempt 1:
بعد از 1 ثانیه

Attempt 2:
بعد از 5 ثانیه

Attempt 3:
بعد از 30 ثانیه

در عمل باید از:
Exponential Backoff
Jitter
Maximum Attempts
Error Classification
Provider Retry-After
استفاده شود.
همه‌ی خطاها هم نباید Retry شوند.
مثلاً:
Temporary Timeout:
احتمالاً Retry شود

Rate Limit:
با Backoff و رعایت Retry-After

Invalid Phone Number:
Retry نکن

Blocked Destination:
Retry نکن

پیام‌های شکست‌خورده‌ی موقت بهتر است وارد صفی مانند این شوند:
sms-retry

و پیام‌هایی که پس از تعداد مشخصی تلاش همچنان شکست خورده‌اند، به اینجا منتقل شوند:
sms-dead-letter

☠️ ءDead Letter Queue
اگر یک پیام بعد از چند بار تلاش پردازش نشود، نباید برای همیشه در صف اصلی بماند.
مثلاً:
Max Attempts = 5

بعد از پنجمین شکست:
Main Queue
↓
Dead Letter Queue

ءDLQ برای این موارد مفید است:
بررسی علت شکست
اصلاح داده‌ی خراب
ءRetry دستی
گزارش‌گیری
جلوگیری از گیرکردن صف اصلی
اما DLQ نباید تبدیل به سطل زباله شود.
باید برای آن:
Monitoring
Alert
Retention Policy
و فرآیند بررسی داشته باشیم.
🧱 ءDuplicate؛ آیا یک پیامک ممکن است دوبار ارسال شود؟ بله.
فرض کن Provider پیامک را دریافت کرده، اما پاسخ موفقیت به سیستم ما نرسیده است:
Our Service → Provider
│
├── SMS sent
└── Response lost

سیستم ما فکر می‌کند ارسال شکست خورده و دوباره Retry می‌کند:
Retry → Provider

حالا ممکن است کاربر دو پیامک دریافت کند.
برای کاهش این مشکل باید از یک شناسه‌ی یکتا استفاده کنیم:
{
"messageId": "sms-8f91",
"idempotencyKey": "otp-login-user-42-request-981"
}

اما یک نکته‌ی مهم:
داشتن Idempotency Key در سیستم خودمان، تضمین نمی‌کند Provider نیز ارسال را دقیقاً یک‌بار انجام دهد.

این موضوع به قابلیت‌های خود Provider وابسته است.
پس باید:
وضعیت ارسال را ذخیره کنیم؛
شناسه‌ی پیام را به Provider منتقل کنیم، اگر پشتیبانی می‌شود؛
ءCallback و Delivery Report را مدیریت کنیم؛
و Duplicate احتمالی را در طراحی در نظر بگیریم.
⏱️ پیامک قدیمی همیشه ارزش ارسال ندارد
فرض کن پیامک OTP مربوط به ۲۰ دقیقه قبل هنوز در Queue است.
ارسال آن دیگر فایده‌ای ندارد.
یا پیامک وضعیت سفارش مربوط به سفارشی است که لغو شده.
پس هر پیام باید اطلاعاتی مانند این داشته باشد:
{
"messageId": "msg-123",
"priority": "Critical",
"createdAt": "2026-09-15T17:00:00Z",
"expiresAt": "2026-09-15T17:01:00Z",
"attempt": 0
}

ءDispatcher قبل از ارسال بررسی می‌کند:
اگر now > expiresAt:
پیام را منقضی کن
ارسال نکن

این موضوع برای جلوگیری از Stale Work مهم است.
گاهی پردازش‌کردن یک پیام قدیمی بدتر از پردازش‌نکردن آن است.
🎯 نتیجه‌گیری
در سیستم بزرگ، Priority Queue فقط به معنی این نیست که:
پیام مهم‌تر را زودتر از صف بردار.

طراحی درست باید این مسائل را هم‌زمان حل کند:
Priority
+
Fairness
+
Rate Limiting
+
Retry
+
Idempotency
+
Expiration
+
Dead Letter Queue
+
Observability

پس معماری مناسب برای سیستم پیامک بلکه چیزی شبیه این است:
Application
↓
Classification
↓
Priority Queues
↓
Fair Dispatcher
↓
Provider Rate Limiter
↓
SMS Provider
↓
Delivery Tracking

و مهم‌ترین تصمیم مهندسی:
پیامک OTP و پیامک تبلیغاتی نباید فقط به خاطر اینکه هر دو «SMS» هستند، با یک SLA و یک مسیر پردازش مدیریت شوند.

چون در سیستم‌های واقعی، همه‌ی پیام‌ها ارزش یکسانی ندارند. 📩
More from @csharpgeeks
  1. Sep 22, 2026یه مدتی قراره از دنیای NET. فاصله بگیرم، چون وقتشه برم سربازی. راستش نمیدونم این مدت رو چج…
  2. Sep 20, 2026🔥 حالا مشکل اصلی: Alert Storm فرض کن Database از دسترس خارج شده. ۱۰۰ Pod داری. هر Pod می‌…
  3. Sep 20, 2026🚨 طراحی سیستم Monitoring و Alerting در یک سیستم بزرگ فرض کن ساعت ۳ صبح است. سیستم شما با…
  4. Sep 19, 2026#Engineering_Leadership تصمیم نگرفتن هم یک تصمیم است یه چیز عجیب توی تیم‌های مهندسی: گاهی…
  5. Sep 19, 2026☑ چک‌لیست آماده‌سازی تیم، فرایندها و زیرساخت برای توسعه با AI توجه: هیچ چک‌لیستی جهان‌شمول…
  6. Sep 19, 2026📌پایان یک انتظار طولانی: اعتبارسنجی ناهمگام (Async Validation) در NET 11.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →