پرش به محتوای اصلی
پرش به محتوای مقاله

«توزیع عادلانه منابع»؛ هدف از الگوی جدید صف‌بندی در Node.js

·۲ شهریور ۱۴۰۵۸ دقیقه مطالعه
راهنما
نحوه اندازه‌گیری API تبدیل گفتار به متن Node.js: هدرهای ۴۲۹ و صف‌های مشتری
نحوه اندازه‌گیری API تبدیل گفتار به متن Node.js: هدرهای ۴۲۹ و صف‌های مشتری
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

معرفی الگوی «صف به‌ازای هر مشتری» (Per-tenant Queue) برای APIهای تبدیل گفتار به متن، که برخلاف صف‌های کلی، مانع از اثر Noisy Neighbor در مصرف سهمیه API می‌شود.

تصور کنید یک مشتری پرمصرف، به‌طور اتفاقی تمام بودجهٔ پردازش شما را مصرف کند و کل خط لولهٔ هوش مصنوعی شرکت را برای سایر کاربران متوقف سازد. برای حل این بحران، در ۲۳ اوت ۲۰۲۶، یک راهنمای فنی در dev.to الگویی معماری برای APIهای بازشناسی گفتار (ASR) در محیط Node.js معرفی کرد که با ایزوله‌کردن حجم کاری هر مشتری، از این شکست‌های سیستمی جلوگیری می‌کند.

بسیاری از توسعه‌دهندگان در ابتدا از طراحی ساده‌ای استفاده می‌کنند: ارسال مستقیم فایل صوتی به API و انتظار برای پاسخ. این رویکرد خطرناک است چون تأخیر کاربر را با ظرفیت ارائه‌دهنده گره می‌زند. اگر یک مشتری دسته‌ای عظیم از فایل‌ها را آپلود کند، تمام ظرفیت هم‌زمانی (Concurrency Budget) را اشغال کرده و سایر کاربران را در وضعیت انتظار می‌گذارد. علاوه بر این، در این مدل، یک درخواست HTTP ساده مسئول کاری است که ممکن است بسیار طولانی‌تر از زمان تعیین‌شده برای Timeout باشد و منجر به قطع شدن اتصال پیش از دریافت پاسخ شود.

برای حل این مشکل، معماری پیشنهادی فرآیند تبدیل متن را به یک صف اختصاصی برای هر مشتری منتقل می‌کند. در این حالت، سیستم به‌جای درخواست مستقیم، کار را سریعاً می‌پذیرد، یک شناسهٔ کار (Job ID) اختصاص می‌دهد و آن را به‌صورت عادلانه زمان‌بندی می‌کند. این کار باعث می‌شود چرخهٔ درخواست HTTP از زمان واقعی پردازش — که برای فایل‌های صوتی طولانی بسیار زیاد است — جدا شود. برای یک استودیوی بازی‌سازی، هدف تنها دریافت متن نیست، بلکه اجرای مجموعه‌ای از عملیات در CRM است که به یک ناشر، شریک پلتفرم یا خریدار تبلیغات متصل باشد. این سطح از انتساب (Attribution) برای پاسخ به این سؤال دشوار ماهانه ضروری است: کدام مشتری دقیقاً باعث ایجاد این هزینهٔ هوش مصنوعی شده است؟

همان‌طور که در تحلیل‌های قبلی ما درباره‌ی بهینه‌سازی هزینه‌های استنتاج اشاره کردیم، جداسازی لایه‌ی پذیرش از لایه‌ی اجرا، کلید مقیاس‌پذیری در محیط‌های چندمستاجری (Multi-tenant) است.

مدیریت محدودیت نرخ (Rate Limit) ۴۲۹

هستهٔ این سیستم نحوهٔ برخورد با پاسخ‌های HTTP 429 (درخواست‌های بیش از حد) است. به نقل از این راهنما، خطای ۴۲۹ باید به‌جای یک شکست، به‌عنوان یک «پاسخ زمان‌بندی» تلقی شود. از آن‌جا که ارائه‌دهندگان مختلف محدودیت‌های متفاوتی را بر اساس حساب کاربری و قراردادهای مختلف اعمال می‌کنند، زمان‌بند نباید فرض کند که یک شمارندهٔ جهانی ساده برای درخواست در دقیقه (RPM) تمام خطاهای ۴۲۹ را توضیح می‌دهد.

  • هدرهای Retry-After: سیستم باید مقدار Retry-After را تحلیل کند. این سیستم باید هر دو فرمت «ثانیه‌های صحیح» (Integer-seconds) و «تاریخ HTTP» (HTTP-date) را پشتیبانی کند. این مقدار به عنوان حداقل تأخیر پیش از تلاش بعدی در نظر گرفته می‌شود.
  • عقب‌نشینی جایگزین (Fallback Backoff): اگر هدر مذکور موجود نباشد یا نامعتبر باشد، سیستم باید از روش Exponential Backoff (عقب‌نشینی نمایی) با سقف مشخص، همراه با Jitter (تغییرات تصادفی کوچک) استفاده کند. ایجاد یک حلقه تکرار سریع (Tight retry loop) توصیه نمی‌شود، زیرا باعث مصرف بیهوده درخواست‌ها شده و روند بازیابی را کندتر می‌کند. این موضوع یادآور چالش‌های مدیریت خطا در درخواست‌های مدل‌های زبانی است که در تحلیل ما درباره اشتباهات رایج بازخوانی درخواست‌های LLM و راهکارهای TypeScript به تفصیل بررسی شده است.
  • تفکیک خطاها: پاسخ‌های 4xx غیر از ۴۲۹ — مانند خطاهای مربوط به قابلیت‌ها، احراز هویت، پیکربندی یا ورودی‌های نامعتبر — به‌عنوان مشکلات دائمی شناخته می‌شوند. تکرار خودکار این خطاها ناامن است. سیستم باید بدنهٔ پاسخ را برای تشخیص دقیق‌تر همراه با Job ذخیره کند، تلاش را به عنوان «شکست خورده» علامت‌گذاری کند و اجازه دهد یک اپراتور یا یک قانون محصولی (Product Rule) درباره گام بعدی تصمیم بگیرد.

رویکرد ماشین وضعیت (State Machine)

برای پایداری بک‌اند و راستگویی رابط کاربری CRM، این سیستم از یک ماشین وضعیت کوچک با TypeScript استفاده می‌کند. هر کار بین پنج وضعیت صریح جابه‌جا می‌شود: pending (در انتظار)، running (در حال اجرا)، retry_wait (انتظار برای تکرار)، complete (تکمیل شده) و failed (شکست خورده).

این ساختار اجازه می‌دهد یک Worker مسئول تماس با ارائه‌دهنده باشد، در حالی که اپلیکیشن اصلی پاسخگو باقی می‌ماند. درخواست آپلود صرفاً شناسهٔ کار و وضعیت pending را برمی‌گرداند و مدیریت تعامل با API و جابه‌جایی بین وضعیت‌ها بر عهدهٔ Worker است.

جزئیات پیاده‌سازی

  • پذیرش مشتری: Worker در هر دور پردازش، تنها یک کارِ سررسیده برای هر مشتری می‌پذیرد. این سیاست محافظه‌کارانه تضمین می‌کند که یک ناشر بازی با ۲۰ آپلود هم‌زمان، نتواند مانع از پردازش فایل‌های یک شریک کوچک‌تر شود.
  • یکتایی (Idempotency): سیستم از یک Job ID ثابت استفاده می‌کند که به‌عنوان کلید یکتایی (Idempotency Key) عمل می‌کند. این امر تضمین می‌کند که در صورت تکرار یک عملیات نوشتن، اگر ارائه‌دهنده از این قرارداد پشتیبانی کند، کارهای تکراری در سمت او ایجاد نشود.
  • منطق TypeScript: مدل داده‌ای Job در مثال ارائه شده شامل tenantId (شناسه مشتری)، audioUrl (آدرس فایل)، audioMinutes (دقایق صوتی)، تعداد تلاش‌ها (attempt)، برچسب زمانی اجرای بعدی (nextRunAt) و وضعیت فعلی (State) است.
  • بررسی آمادگی: سیستم شامل تابع inspectInfraiAsrReadiness است که در ابتدای شروع، آمادگی سرویس ASR را از طریق یک URL اکتشافی بررسی می‌کند. این تابع تا چهار بار تلاش می‌کند و حتی در مرحله اکتشاف نیز به خطاهای ۴۲۹ احترام می‌گذارد.

محاسبه هزینه و اندازه‌گیری

اندازه‌گیری مصرف اغلب به عنوان یک موضوع ثانویه دیده می‌شود، اما در این طراحی، اندازه‌گیری در لحظهٔ پذیرش ادغام شده است. سیستم مقدار audioMinutes و tenantId را پیش از ارسال درخواست به API ثبت می‌کند تا در هفتهٔ صدور صورت‌حساب، نیاز به بازسازی این ارقام نباشد.

بر اساس مستندات این گزارش، ثبت این معیارها در مرز ورود داده برای شفافیت مالی حیاتی است. راهنما توصیه می‌کند داده‌های زیر برای هر کار ذخیره شوند:

  • شناسه مشتری (Tenant ID) و شناسه کار (Job ID)
  • مدت‌زمان رسانه (دقایق صوتی)
  • نام ارائه‌دهنده و شناسه درخواست ارائه‌دهنده (Provider's Request ID)
  • تعداد تلاش‌ها و برچسب‌های زمانی
  • وضعیت نهایی (Terminal State)
  • هزینه واقعی صورت‌حساب شده (اگر توسط ارائه‌دهنده ارائه شود) یا واحد مصرف خاص مورد نیاز برای تطبیق صورت‌حساب.

این روش مانع از آن می‌شود که هزینه‌های تبدیل متن و خلاصه‌سازی به‌صورت یک مبلغ مبهم ترکیب شوند، زیرا یک تماس فروش می‌تواند دو نوع مصرف متفاوت از هوش مصنوعی (یکی برای تبدیل گفتار به متن و دیگری برای خلاصه‌سازی) ایجاد کند و هر کدام باید به طور مجزا ردیابی شوند.

انتخاب ارائه‌دهنده و دسته‌بندی (Batching)

این راهنما چندین ارائه‌دهنده را برای این گردش کار ارزیابی کرده و اشاره می‌کند که آمادگی قابلیت‌ها، هدرهای سهمیه و متادیتای صورت‌حساب بین فروشندگان قابل انتقال نیستند:

  • OpenAI: گزینه‌ای برای آداپتور مستقیم؛ نیازمند تأیید در دسترس بودن مدل فعلی، محدودیت‌های فایل و گزارش‌های مصرف است.
  • Azure OpenAI: کاربردی است اگر کل حجم کاری هوش مصنوعی در Azure باشد، هرچند کاربران باید بررسی کنند که قابلیت‌های گفتار در همان یکپارچگی (Integration) موجود باشد.
  • Vertex AI و Gemini: گزینه‌ای برای کاربران گوگل کلاود؛ نیازمند تأیید ورودی‌های صوتی و در دسترس بودن منطقه‌ای است.
  • Amazon Transcribe: مناسب برای محیط‌های AWS؛ راهنما پیشنهاد می‌کند تبدیل گفتار و استفاده از مدل‌های Bedrock در مراحل بعدی را به عنوان عملیات‌های اندازه‌گیری شده جداگانه نگه دارید.
  • Infrai: رابط REST خود-توصیف‌کننده‌ای با یک کلید و یک صورت‌حساب واحد ارائه می‌دهد که تطبیق اعتبارنامه‌ها را کاهش می‌دهد. با این حال، در حال حاضر برای این حجم خاص از کارهای ASR مناسب نیست زیرا کاتالوگ آن مدل تبدیل متن در دسترس ندارد.

پردازش دسته‌ای (Batching) به‌عنوان بهینه‌سازی ثانویه برای زمانی پیشنهاد شده است که تماس‌ها می‌توانند منتظر بمانند یا حجم ورود داده‌ها نوسانی باشد. با این حال، Batching یک مکانیسم تعمیری نیست. اگر یک درخواست دارای خطای پیکربندی 4xx غیرقابل تکرار باشد، جمع کردن ۱۰۰ نسخه از آن در یک دسته، فقط منجر به ایجاد یک واحد رد شدهٔ بزرگ‌تر می‌شود. علاوه بر این، دسته‌بندی نیاز به انصاف بین مشتریان را از بین نمی‌برد؛ سازندهٔ دسته (Batch Builder) همچنان به سهمیه‌های مشخص نیاز دارد تا از اشغال تمام جایگاه‌ها توسط یک ناشر جلوگیری کند.

اعتبارسنجی و حسابرسی

این تغییر رویکرد، تمرکز را از «بیشینه توان عملیاتی بنچمارک» به «شفافیت هزینه و انصاف برای هر مشتری» منتقل می‌کند. برای تأیید پیاده‌سازی، تست فشار با سه نوع پاسخ ۴۲۹ (عددی، تاریخ‌محور و بدون هدر) پیشنهاد شده است. موفقیت زمانی است که هیچ تکراری زودتر از موعد شروع نشود، هیچ مشتری پرمصرفی (Noisy Tenant) مانع دیگران نگردد، یک Job ID ثابت در تمام تلاش‌ها باقی بماند و رابط کاربری هرگز وضعیت retry_wait را به عنوان شکست نمایش ندهد. علاوه بر این، باید یک درخواست نامعتبر ارسال شود تا تأیید گردد که بدون تکرار، به وضعیت failed می‌رسد.

توسعه‌دهندگان باید اکنون دفاتر حساب مشتریان خود را با چهار برش داشبورد خاص حسابرسی کنند:
۱. سن صف به تفکیک مشتری.
۲. تعداد خطاهای ۴۲۹ به تفکیک ارائه‌دهنده و مشتری.
۳. تعداد تلاش‌ها به‌ازای هر دقیقه تکمیل شده.
۴. تفکیک شکست‌های نهایی (خطاهای ۴۲۹ در برابر سایر پاسخ‌های 4xx).

هزینه هر مشتری باید تنها از داده‌های صورت‌حساب یا متادیتای صریح ارائه‌دهنده استخراج شود، نه بر اساس تخمین از تعداد درخواست‌ها، به‌ویژه اگر صورت‌حساب بر اساس مدت‌زمان باشد. با نگاه به ارائه‌دهنده API به‌عنوان یک منبع محدود — و نه یک لوله بی‌نهایت — توسعه‌دهندگان می‌توانند سرویس‌های سازمانی پیش‌بینی‌پذیرتری بسازند.

گام بعدی شما

  • اگر از APIهای هوش مصنوعی در محیط Multi-tenant استفاده می‌کنید، سیستم پذیرش خود را از مدل «درخواست مستقیم» به «صف‌های مجزا» تغییر دهید.
  • منطق تحلیل هدر Retry-After را به Workerهای خود اضافه کنید تا از مسدود شدن حساب کاربری (Ban) جلوگیری کنید.
  • متادیتای مصرف (مانند دقایق صوتی) را در لحظه ورود داده ثبت کنید، نه در لحظه دریافت پاسخ.

اما مدیریت این صف‌ها در مقیاس میلیون‌ها درخواست، چالش‌های جدیدی در لایه پایگاه‌داده ایجاد می‌کند — به تحلیل ما درباره‌ی بهینه‌سازی Redis برای صف‌های توزیع‌شده مراجعه کنید.

چرا این موضوع مهم است؟

این معماری از توقف کامل سرویس‌های سازمانی به‌دلیل مصرف بیش از حد یک کاربر جلوگیری می‌کند. با تکیه بر تجربه استقرار در محیط‌های ابری، جداسازی صف‌ها تنها راه تضمین انصاف (Fairness) در توزیع منابع محدود GPU است.

تأثیر برای ایران

برای توسعه‌دهندگان ایرانی که از APIهای خارجی از طریق واسطه‌ها استفاده می‌کنند، پیاده‌سازی این مدل برای مدیریت هزینه‌های دلاری و جلوگیری از مسدود شدن اکانت‌های مشترک حیاتی است.

·نگاه ما
تحریریه دات‌هوش

جایگزینی مدل‌های Synchronous با صف‌های ایزوله، در واقع پذیرش این واقعیت است که APIهای هوش مصنوعی برخلاف دیتابیس‌های سنتی، منابعی ناپایدار و دارای محدودیت‌های سخت هستند. این رویکرد، مفهوم «پایداری» را از حذف خطا به «مدیریت هوشمندانه تأخیر» تغییر می‌دهد. در عمل، این یعنی توسعه‌دهنده باید به‌جای تلاش برای دور زدن Rate Limit، آن را به‌عنوان بخشی از منطق زمان‌بندی اپلیکیشن بپذیرد.

منابع

این گزارش با خط‌لولهٔ خودکار دات‌هوش از منابع معتبر جهانی تدوین و زیر نظر تحریریه منتشر شده است. روش کار ما

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.