بهینه سازی پاسخ به عقب: صف، async، فشار پشتی
1) چرا: اهداف و SLO ها
هدف یک پاسخ سریع پایدار حتی در زیر انفجار است. کسب و کار این SLO را بیان می کند:- API (CRUD/دایرکتوری ها): p95 ≤ 250-400 ms، نرخ خطا <1٪.
- پرداخت/حل و فصل (ناهمزمان): SLA داخلی برای تایید ≤ 2-5 دقیقه، و مشتری - 202/Accepted فوری + poller وضعیت/webhook.
- WS/زمان واقعی: RTT p95 ≤ 120 мс، قطع ≤ 0. 5%.
کلید: برای باز کردن مراحل «آهسته» (ارائه دهندگان، پایگاه های داده، API های خارجی) از پاسخ کاربر از طریق صف و محدودیت بار صالح.
2) تصویر اصلی: جایی که تاخیر گرفته شده است
تنگناها: پایگاه داده (استخر/شاخص)، ارائه دهندگان خارجی (PSP/بازی)، مسدود کردن I/O، GC/توقف جهان، سریال JSON، «سنگین» تجمع.
علائم: رشد p99، صف اتصال DB، انفجار مجدد، طوفان مجدد.
پادزهر: خطوط لوله ناهمزمان + فشار پشتی + زمان بندی/عقب نشینی + idempotency.
3) الگوهای ناهمزمان: SEDA و CQRS
SEDA (staged event-driven architecture): پردازش را به مراحل تقسیم می کند (ورود → اعتبار → نوشتن → ادغام → اطلاع رسانی). هر کدام محدودیت های نوبت و همزمانی خود را دارند.
CQRS: خواندن و نوشتن جداگانه. نوشتن - به ورود/پایگاه داده، خواندن - از پیش بینی ها/کش ها.
Outbox: این رویداد به صورت اتمی همراه با رکورد منتشر می شود (اجتناب از پیام های «از دست رفته»).
Saga: فرآیندهای کسب و کار طولانی با معاملات جبران کننده به جای معاملات جهانی.
4) صف و جریان: انتخاب و تنظیم
RabbitMQ/NATS JetStream - دستورات وظیفه (صف کار)، کافکا - رویدادها/جریان با پخش.
تنظیمات که بر پاسخ تاثیر می گذارد:- Prefetch/max in-flight: تعداد پیام های پردازش شده همزمان در هر کارگر (به عنوان مثال، 16-64) را محدود کنید تا پایگاه داده/API خارجی را مسدود نکنید.
- آکر/تکرار می کند: «ACK» پس از ضبط idempoint ؛ تاخیر نمایی و تکرار jitter.
- DLQ/پارکینگ: هیچ عقب نشینی بی پایان وجود دارد - پس از N تلاش, می رود به مرده نامه صف.
- پارتیشن بندی (کافکا): کلید توسط جوهر (userId/txnId) برای سفارش ؛ موازی از طریق تعداد احزاب.
5) فشار پشتی - چگونه غرق نشویم
ایده: فقط به همان اندازه که می توانید در تأخیر SLO پردازش کنید.
تکنسین ها:- کنترل پذیرش: محدود کردن رقابت (semaphore/worker-pool) برای هر وابستگی خارجی: پایگاه داده، PSP، ارائه دهنده بازی.
- شکل دادن به ترافیک: سطل نشانه/سطل نشتی در ورودی سرویس و در مسیرهای بحرانی.
- صف با مرز بالا: هنگامی که کامل، قطع دم (429/503 + Retry-After) و یا انتقال به ASAP دسته ای.
- همزمانی تطبیقی (AIMD): افزایش موازی در موفقیت، کاهش در وقفه.
- قطع کننده مدار: 'بسته → باز → نیمه باز' توسط خطاها/زمان از API خارجی ؛ هنگامی که باز - تخریب (کش/خرد).
برو sem: = ساخت (چان struct {}، 64 )//حد رقابت به DB/PSP
دسته FUNC (REQ) {
انتخاب کنید {
مورد sem <- ساختار {}:
به تعویق انداختن func () {<-sem} ()
ctx، لغو: = زمینه. با اتمام وقت (REQ. ctx، 300 بار. میلی ثانیه)
تعویق لغو ()
res, err: = db. انجام دهید (ctx, req)
اگر err = = زمینه DeadlineExceeded {متریک. مرخصي ها. شرکت () ؛ بازگشت خیلی آهسته ()}
بازگشت Ok (res)
پیش فرض:
متریک ها فشار به عقب شرکت ()
Return TooBusy (429 ", Retry-After: 0. 2")
}
}
6) زمان، عقب نشینی و jitter: «سه نهنگ زنده ماندن»
وقفه های کوتاه تر از SLO: اگر SLO 400 ms، وقفه به DB/ارائه دهنده 250-300 ms ؛ کل زمان درخواست <400-600 ms.
Retrai محدود و هوشمند: حداکثر 1-2 تلاش، فقط برای عملیات ایمن (idempotent)، با توان و لرزش.
Coalessing: Aggregate replays برای یک کلید واحد.
شبه کد (توان + لرزش):پایتون برای تلاش در محدوده (0، 2):
سعی کنید:
return call (dep, timeout = 0. 3)
به جز اتمام وقت:
backoff = (0) 05 (2attempt)) + تصادفی. یونیفرم (0, 0. 05)
خواب (عقب نشینی)
بالا بردن UpstreamUnavailable
7) هویت و تقسیم بندی
Idempotency-Key در HTTP (سپرده ها، پرداخت ها)، 'operation _ id' در پایگاه داده (شاخص منحصر به فرد).
صندوق ورودی/صندوق خروجی: کتابهای وب ورودی - همیشه از طریق یک جدول صندوق ورودی غیرقابل تغییر با dedupe توسط «event _ id» ؛ خروجی - از صندوق خروجی توسط معامله.
دقیقا یک بار «در معنی»: ما اجازه تحویل/اجرای مکرر را می دهیم، اما تنها یک اثر وجود دارد.
8) API سریع برای عملیات آهسته
پاسخ همزمان: 201/202 + URL وضعیت ('/status/{ id} ')، نکات ETA و یکپارچهسازی با سیستمعامل.
Webhooks/Server-Sent Events/WS - فشار دولت زمانی که آماده است.
نظم و انضباط مشتری: 'Retry-After'، idempointence، حد رای گیری.
مثال پاسخ:جی سون
HTTP/1 است. 1 202 پذیرفته شده است
محل سکونت :/ v1/withdrawals/req_9f2/status
تلاش مجدد پس از: 2
{
«request_id": «req_9f2,» «دولت»: «پردازش»، «next_check_sec": 2
}
9) به حداقل رساندن کار گرم
چیزهای سنگین را در پس زمینه قرار دهید: تبدیل، تجمع، اطلاعیه ها، نوشتن به DWH.
کش و پیش بینی: معمولا به عنوان خوانده شده - کش کنار با TTL کوتاه و ناتوانی رویداد.
الگوهای دسته ای: تماس های خارجی گروهی (به عنوان مثال محدودیت ارائه دهنده درخواست یک بار در N ms).
سریال سازی: کدک های سریع (protobuf/msgpack) برای ارتباطات سرویس به سرویس ؛ JSON تنها در لبه.
10) DB تحت کنترل
استخر اتصال: مرزهای بالا (بر اساس هسته/IO)، صف به استخر را فعال کنید.
شاخص ها و برنامه: p95 توضیح + خودکار رگرسیون برنامه ها.
درخواست وقفه: کوتاه, 'statement _ timeout' (Postgres).
ردیف های داغ/قفل: shardings کلیدی، قفل خوش بینانه (نسخه تعادل)، حماسه به جای یک معامله «یکپارچه».
11) WebSocket/زمان واقعی
محدود کننده خبرنامه: پخش دسته، حداکثر msgs/ثانیه در هر اتصال.
فشار داخلی: صف پیام خروجی با یک کلاه ؛ در سرریز - رها کردن اولویت پایین.
مسیریابی چسبنده و PDB در هنگام انتشار - به طوری که برای تولید یک طوفان مجدد.
12) قابلیت مشاهده به طوری که نمی توان حدس زد
معیارهای (RED/USE + فشار پشتی):- 'request _ rate'، 'error _ ratio'، 'latency _ p95/p99' در مسیرها.
- 'queue _ depth'، 'lag _ seconds'، 'consumer _ flight'، 'retries _ total'، 'dlq _ rate'.
- 'backpressure _ drops', 'admission _ rejects', 'circuit _ open'.
- Для БД: 'connections _ in _ use/max', 'locks', 'slow _ queries'.
- Traces: spans 'queue → worker → db/psp' with tags 'operation _ id', 'partition', 'retry'.
- سیاهههای مربوط: ساختاری، با 'trace _ id'، بدون PII ؛ رویدادهای فردی «مدار باز/بسته».
13) تست بار
مدل باز (ورودی/ثانیه) برای انفجار ؛ مدل بسته (VUs) برای جلسات.
پروفایل: پشت سر هم کوتاه 60-120 ثانیه و خیس 1-4 ساعت.
خرابی های تزریق: API خارجی را با 200-500 میلی ثانیه کاهش دهید، به p99/retrai/صف نگاه کنید.
معیارهای منطقه سبز: بدون رشد «صف _ تاخیر»، p95 پایدار، «dlq_rate≈0».
14) ایمنی و قابلیت اطمینان
صفهای TLS/mTLS، امضای پیام، نظارت بر طرحواره (Avro/Protobuf + Schema Registry).
تولید کننده Idempotent (کافکا)، دقیقا یک بار TX که در آن توجیه شده است.
حالت هرج و مرج: دوره ای «رها کردن» اعتیاد و نگاه به تخریب (مدار، سقوط).
15) نمونه هایی از «قطعه» تنظیمات
Nginx/نماینده شکل دادن به ورودی:nginx limit_req_zone منطقه $binary_remote_addr = api: نرخ 10m = 20r/s ؛
سرور {
محل سکونت/API/{
منطقه limit_req = api burst = 40 nodelay;
proxy_read_timeout 0 6 ثانیه ؛ # کوتاه تر از SLO proxy_connect_timeout 0 است. 2 ها ؛
}
}
RabbitMQ (پیش فرض):
اساسی است. qos (prefetch_count = 32) # CPU/IO تعادل
مصرف کننده کافکا (قطعه جاوا):
جاوا پروکسی. قرار داده شده (ConsumerConfig. MAX_POLL_RECORDS_CONFIG، 200) ؛
لوازم جانبی قرار داده شده (ConsumerConfig. FETCH_MAX_BYTES_CONFIG، 5_000_000) ؛
لوازم جانبی قرار داده شده (ConsumerConfig. MAX_POLL_INTERVAL_MS_CONFIG، 60_000) ؛
16) چک لیست پیاده سازی (prod-ready)
- مسیرهای بحرانی به پاسخ همزمان و پردازش ناهمزمان (SEDA) تقسیم می شوند.
- کنترل پذیرش و محدودیت رقابت برای وابستگی های خارجی.
- وقفه ها کوتاه تر از SLO هستند ؛ retrai ≤ 2، با توان و لرزش ؛ ائتلاف کردن.
- قطع کننده مدار + تخریب (حافظه پنهان/خرد)، سیاست نیمه باز.
- صف/جریان: پیش فرض/در پرواز، DLQ، دسته های کلیدی.
- Idempotency (operation_id/Idempotency-Key)، صندوق پستی/صندوق، deduplication.
- کش: کش کنار، TTL کوتاه + ناتوانی رویداد.
- DB: محدودیت استخر، statement_timeout، شاخص ها، استراتژی های ضد قفل.
- WS: محدودیت پیام، butching، مسیریابی چسبنده، PDB.
- قابلیت مشاهده: فشار برگشتی/صف/معیارهای مجدد، مسیرهای پایان به پایان، داشبورد.
- تست بار و شکست (باز + بسته، پشت سر هم + خیس خوردن)، معیارهای منطقه سبز.
خلاصه رزومه
یک backend سریع «ایجاد یک حافظه پنهان دیگر» نیست، بلکه یک جریان کنترل شده است: ورود محدود و سنگین است - در پس زمینه، هر مرحله با صف و محدودیت ها، بازپرداخت ها نادر و هوشمند هستند و زنجیره ها توسط قطع کننده مدار و idempointency محافظت می شوند. نظم و انضباط، مشاهده پذیری و تست های استرس منظم را اضافه کنید - و p95/p99 شما حتی تحت انفجار و هوی و هوس ارائه دهندگان خارجی سبز باقی خواهد ماند.