ساخت برای سیستم‌های بزرگ و کارهای پس‌زمینه طولانی‌مدت. اعتبار: ایلیاس چبی در آنسپلش ماه‌ها پیش، من نقشی را پذیرفتم که نیاز به ساخت زیرساخت داشتساخت برای سیستم‌های بزرگ و کارهای پس‌زمینه طولانی‌مدت. اعتبار: ایلیاس چبی در آنسپلش ماه‌ها پیش، من نقشی را پذیرفتم که نیاز به ساخت زیرساخت داشت

ساخت اسپاتیفای برای موعظه‌ها.

2025/12/11 21:15

ساخت برای سیستم‌های بزرگ و کارهای پس‌زمینه طولانی مدت.

اعتبار: ایلیاس چبی در Unsplash

چند ماه پیش، نقشی را به عهده گرفتم که نیاز به ساخت زیرساخت برای پخش رسانه (صوتی) داشت. اما فراتر از ارائه صوتی به صورت قطعات قابل پخش، کارهای پردازش رسانه‌ای طولانی مدت و یک خط لوله RAG گسترده وجود داشت که برای رونویسی، تبدیل کد، جاسازی و به‌روزرسانی‌های رسانه‌ای متوالی طراحی شده بود. ساخت یک MVP با ذهنیت تولید باعث شد تا زمانی که به یک سیستم بی‌نقص دست یافتیم، تکرار کنیم. رویکرد ما یکی از مواردی بوده است که در آن ویژگی‌ها و پشته اولویت‌های زیربنایی را ادغام کردیم.

نگرانی اصلی:

در طول ساخت، هر تکرار به عنوان پاسخی به نیاز فوری و اغلب "فراگیر" آمد. نگرانی اولیه صف‌بندی کارها بود، که به راحتی با Redis کافی بود؛ ما به سادگی شلیک کردیم و فراموش کردیم. Bull MQ در چارچوب NEST JS به ما کنترل بهتری بر تلاش‌های مجدد، پس‌افتادگی‌ها و صف نامه‌های مرده داد. به صورت محلی و با چند محموله در تولید، جریان رسانه را درست انجام دادیم. ما به زودی با وزن نظارت‌پذیری مواجه شدیم:
لاگ‌ها → ثبت کارها (درخواست‌ها، پاسخ‌ها، خطاها).
معیارها → چقدر / چند وقت یکبار این کارها اجرا می‌شوند، شکست می‌خورند، تکمیل می‌شوند و غیره.
ردیابی‌ها → مسیری که یک کار در سرویس‌ها طی کرد (توابع/روش‌های فراخوانی شده در مسیر جریان).

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

ساخت برای نظارت‌پذیری

چالش مدیریت گردش کارهای پیچیده و طولانی مدت بک‌اند، جایی که خرابی‌ها باید قابل بازیابی باشند و وضعیت باید پایدار باشد، Inngest نجات معماری ما شد. این اساساً رویکرد ما را بازسازی کرد: هر کار پس‌زمینه طولانی مدت تبدیل به یک تابع پس‌زمینه می‌شود که توسط یک رویداد خاص فعال می‌شود.

به عنوان مثال، یک رویداد Transcription.request یک تابع TranscribeAudio را فعال می‌کند. این تابع ممکن است شامل اجرای مراحلی برای: fetch_audio_metadata، deepgram_transcribe، parse_save_trasncription و notify_user باشد.

تجزیه گردش کار: تابع Inngest و اجرای مراحل

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

  • منطق اتمی: یک تابع منطق کسب و کار شما را قدم به قدم اجرا می‌کند. اگر یک مرحله شکست بخورد، وضعیت کل اجرا حفظ می‌شود و اجرا می‌تواند دوباره تلاش شود. این تابع را از ابتدا مجدداً راه‌اندازی می‌کند. مراحل فردی یا اجرای مراحل را نمی‌توان به تنهایی دوباره امتحان کرد.
  • سریالی‌سازی پاسخ: یک اجرای مرحله با پاسخ آن تعریف می‌شود. این پاسخ به طور خودکار سریالی می‌شود، که برای حفظ ساختارهای داده پیچیده یا با نوع قوی در مرزهای اجرا ضروری است. اجرای مراحل بعدی می‌تواند این پاسخ سریالی شده را به طور قابل اعتماد تجزیه کند، یا منطق می‌تواند برای کارایی در یک مرحله واحد ادغام شود.
  • جداسازی و زمان‌بندی: در یک تابع، می‌توانیم به طور مشروط رویدادهای جدید و وابسته را در صف قرار دهیم یا زمان‌بندی کنیم، که الگوهای پیچیده fan-out/fan-in و زمان‌بندی طولانی مدت تا یک سال را فعال می‌کند. خطاها و موفقیت‌ها در هر نقطه می‌توانند گرفته شوند، شاخه‌بندی شوند و در ادامه گردش کار مدیریت شوند.

خلاصه تابع Inngest:

import { inngest } from 'inngest-client';

export const createMyFunction = (dependencies) => {
return inngest.createFunction(
{
id: 'my-function',
name: 'My Example Function',
retries: 3, // retry the entire run on failure
concurrency: { limit: 5 },
onFailure: async ({ event, error, step }) => {
// handle errors here
await step.run('handle-error', async () => {
console.error('Error processing event:', error);
});
},
},
{ event: 'my/event.triggered' },
async ({ event, step }) => {
const { payload } = event.data;

// Step 1: Define first step
const step1Result = await step.run('step-1', async () => {
// logic for step 1
return `Processed ${payload}`;
});

// Step 2: Define second step
const step2Result = await step.run('step-2', async () => {
// logic for step 2
return step1Result + ' -> step 2';
});

// Step N: Continue as needed
await step.run('final-step', async () => {
// finalization logic
console.log('Finished processing:', step2Result);
});

return { success: true };
},
);
};

مدل رویداد محور Inngest بینش دقیقی در مورد هر اجرای گردش کار ارائه می‌دهد:

  • ردیابی جامع رویداد: هر اجرای تابع در صف در مقابل رویداد اصلی آن ثبت می‌شود. این یک مسیر واضح و سطح بالا از تمام فعالیت‌های مربوط به یک اقدام کاربر واحد ارائه می‌دهد.
  • بینش‌های اجرای دقیق: برای هر اجرای تابع (هم موفقیت‌ها و هم شکست‌ها)، Inngest از طریق گزارش‌دهی ack (تأیید) و nack (تأیید منفی) خود، لاگ‌های دقیقی ارائه می‌دهد. این لاگ‌ها شامل ردیابی پشته خطا، محموله‌های کامل درخواست و محموله‌های پاسخ سریالی شده برای هر اجرای مرحله فردی است.
  • معیارهای عملیاتی: فراتر از لاگ‌ها، ما معیارهای مهمی در مورد سلامت تابع به دست آوردیم، از جمله نرخ موفقیت، نرخ شکست و تعداد تلاش مجدد، که به ما امکان می‌دهد به طور مداوم قابلیت اطمینان و تأخیر گردش کارهای توزیع شده خود را نظارت کنیم.

ساخت برای انعطاف‌پذیری

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

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

سیستم صف ساده AWS (SQS) سیستم انتخابی ما بود (اگرچه هر سیستم صف‌بندی قوی قابل انجام است)، با توجه به زیرساخت موجود ما در AWS. ما یک سیستم دو صفی طراحی کردیم: یک صف اصلی و یک صف نامه مرده (DLQ).

ما یک محیط کارگر Elastic Beanstalk (EB) را به طور خاص پیکربندی کردیم تا پیام‌ها را مستقیماً از صف اصلی مصرف کند. اگر یک پیام در صف اصلی توسط کارگر EB به تعداد مشخصی از دفعات پردازش نشود، صف اصلی به طور خودکار پیام ناموفق را به DLQ اختصاصی منتقل می‌کند. این اطمینان می‌دهد که هیچ رویدادی به طور دائم از دست نمی‌رود اگر در فعال‌سازی یا برداشت توسط Inngest شکست بخورد. این محیط کارگر با یک محیط سرور وب EB استاندارد متفاوت است، زیرا تنها مسئولیت آن مصرف و پردازش پیام است (در این مورد، ارسال پیام مصرف شده به نقطه پایانی API Inngest).

درک محدودیت‌ها و مشخصات

بخش کم‌اهمیت و نسبتاً مرتبط با ساخت زیرساخت در مقیاس سازمانی این است که منابع را مصرف می‌کند و آنها طولانی مدت هستند. معماری میکروسرویس مقیاس‌پذیری را برای هر سرویس فراهم می‌کند. ذخیره‌سازی، RAM و زمان‌های وقفه منابع به بازی خواهند آمد. مشخصات ما برای نوع نمونه AWS، به عنوان مثال، به سرعت از t3.micro به t3.small تغییر کرد و اکنون در t3.medium ثابت شده است. برای کارهای پس‌زمینه طولانی مدت و پردازنده-محور، مقیاس‌پذیری افقی با نمونه‌های کوچک شکست می‌خورد زیرا گلوگاه زمانی است که برای پردازش یک کار واحد لازم است، نه حجم کارهای جدیدی که وارد صف می‌شوند.

کارها یا توابع مانند رمزگذاری، جاسازی معمولاً محدود به CPU و محدود به حافظه هستند. محدود به CPU زیرا نیاز به استفاده مداوم و شدید از CPU دارند، و محدود به حافظه زیرا اغلب نیاز به RAM قابل توجهی برای بارگیری مدل‌های بزرگ یا مدیریت کارآمد فایل‌ها یا محموله‌های بزرگ دارند.

در نهایت، این معماری تقویت شده، قرار دادن دوام SQS و اجرای کنترل شده یک محیط کارگر EB مستقیماً در بالادست API Inngest، انعطاف‌پذیری ضروری را فراهم کرد. ما به مالکیت سختگیرانه رویداد دست یافتیم، شرایط مسابقه را در طول افزایش ترافیک حذف کردیم و یک مکانیسم نامه مرده غیر فرار به دست آوردیم. ما از Inngest برای قابلیت‌های هماهنگ‌سازی گردش کار و اشکال‌زدایی آن استفاده کردیم، در حالی که برای حداکثر توان عملیاتی پیام و دوام به اصول اولیه AWS متکی بودیم. سیستم حاصل نه تنها مقیاس‌پذیر است بلکه به شدت قابل حسابرسی است، و با موفقیت کارهای پیچیده و طولانی مدت بک‌اند را به میکرو-مراحل امن، قابل مشاهده و مقاوم در برابر خطا تبدیل می‌کند.


ساخت اسپاتیفای برای موعظه‌ها. در اصل در Coinmonks در Medium منتشر شد، جایی که مردم با برجسته کردن و پاسخ دادن به این داستان به گفتگو ادامه می‌دهند.

سلب مسئولیت: مطالب بازنشرشده در این وب‌ سایت از منابع عمومی گردآوری شده‌ اند و صرفاً به‌ منظور اطلاع‌ رسانی ارائه می‌ شوند. این مطالب لزوماً بازتاب‌ دهنده دیدگاه‌ ها یا مواضع MEXC نیستند. کلیه حقوق مادی و معنوی آثار متعلق به نویسندگان اصلی است. در صورت مشاهده هرگونه محتوای ناقض حقوق اشخاص ثالث، لطفاً از طریق آدرس ایمیل [email protected] با ما تماس بگیرید تا مورد بررسی و حذف قرار گیرد.MEXC هیچ‌ گونه تضمینی نسبت به دقت، جامعیت یا به‌ روزبودن اطلاعات ارائه‌ شده ندارد و مسئولیتی در قبال هرگونه اقدام یا تصمیم‌ گیری مبتنی بر این اطلاعات نمی‌ پذیرد. همچنین، محتوای منتشرشده نباید به‌عنوان توصیه مالی، حقوقی یا حرفه‌ ای تلقی شود و به منزله پیشنهاد یا تأیید رسمی از سوی MEXC نیست.