عنوان:

‫الگوی وب-صف-کارگر: مقیاس‌پذیری با رویکردی عمل‌گرایانه


نویسنده: وحید نصیری
تاریخ: ۱۴۰۴/۰۲/۲۴ ۰۷:۴۶
آدرس: www.dntips.ir
در دنیای توسعه نرم‌افزار، طراحی سیستم‌هایی که بتوانند به‌صورت مقیاس‌پذیر (Scalable) و کارآمد عمل کنند، از اهمیت ویژه‌ای برخوردار است. یکی از الگوهای معماری که به توسعه‌دهندگان کمک می‌کند تا سیستم‌هایی پاسخ‌گو و انعطاف‌پذیر طراحی کنند، الگوی وب-صف-کارگر (Web-Queue-Worker Pattern) است. این الگو با جداسازی پردازش‌های همزمان (Synchronous) و ناهمزمان (Asynchronous) و بهره‌گیری از یک سیستم صف (Queue)، امکان مدیریت وظایف سنگین و زمان‌بر را بدون تأثیر منفی بر تجربه کاربری فراهم می‌کند.

الگوی وب-صف-کارگر چیست؟
الگوی وب-صف-کارگر یک معماری نرم‌افزاری است که برای مدیریت وظایف ناهمزمان در برنامه‌های وب طراحی شده است. در این الگو، سه جزء اصلی وجود دارد: رابط کاربری یا وب (Web)، صف (Queue) و کارگر (Worker). رابط وب، که معمولاً یک API مبتنی بر HTTP است، درخواست‌های کاربران را دریافت می‌کند. اگر درخواست شامل عملیاتی سبک و همزمان مانند پرس‌وجو از پایگاه داده باشد، API مستقیماً پاسخ را تولید می‌کند. اما برای وظایف سنگین یا زمان‌بر، مانند ارسال ایمیل یا پردازش داده‌های پیچیده، API یک پیام را به صف ارسال می‌کند و بلافاصله پاسخ را به کاربر بازمی‌گرداند. سپس، فرآیند کارگر که به‌صورت مستقل عمل می‌کند، پیام را از صف برمی‌دارد و وظیفه مربوطه را اجرا می‌کند.
این جداسازی وظایف باعث می‌شود که رابط کاربری سریع و پاسخ‌گو باقی بماند، حتی زمانی که سیستم با حجم بالایی از درخواست‌ها مواجه است. برای مثال، فرض کنید یک برنامه وب نیاز به تولید گزارش‌های پیچیده دارد. به‌جای اینکه کاربر منتظر تکمیل گزارش بماند، API پیام را به صف اضافه می‌کند و کاربر می‌تواند به کار خود ادامه دهد، درحالی‌که کارگر در پس‌زمینه گزارش را تولید می‌کند.

نحوه پیاده‌سازی در دات‌نت
پیاده‌سازی الگوی وب-صف-کارگر در اکوسیستم دات‌نت معمولاً با استفاده از فریم‌ورک ASP.NET Core برای API و یک سیستم صف مانند RabbitMQ یا Azure Service Bus انجام می‌شود. یکی از نقاط قوت این الگو در دات‌نت، امکان استفاده از یک کدبیس مشترک برای API و کارگر است. این بدان معناست که هر دو مؤلفه می‌توانند از منطق یکسانی استفاده کنند، که نگهداری و استقرار (Deployment) را ساده‌تر می‌کند.
برای مثال، فرض کنید یک برنامه با ASP.NET Core طراحی شده است که کاربران می‌توانند از طریق آن ایمیل‌های خوش‌آمدگویی دریافت کنند. کد زیر نشان‌دهنده کنترلری است که درخواست ارسال ایمیل را به صف اضافه می‌کند:
[HttpPost("send-welcome-email")]
public IActionResult SendWelcomeEmail([FromBody] EmailRequest request)
{
    var message = JsonSerializer.Serialize(request);
    _queueClient.SendMessage(message); // ارسال پیام به صف
    return Ok("درخواست ارسال ایمیل ثبت شد.");
}
در این کد، EmailRequest شامل اطلاعات ایمیل است و _queueClient به یک سرویس صف مانند Azure Service Bus متصل است. پس از ارسال پیام به صف، API بلافاصله پاسخ موفقیت‌آمیز را به کاربر بازمی‌گرداند.
در سمت کارگر، یک برنامه کنسول یا سرویس پس‌زمینه (Background Service) در ASP.NET Core پیام را از صف دریافت می‌کند و ایمیل را ارسال می‌کند:
public class EmailWorker : BackgroundService
{
    private readonly IQueueClient _queueClient;
    private readonly IEmailService _emailService;

    public EmailWorker(IQueueClient queueClient, IEmailService emailService)
    {
        _queueClient = queueClient;
        _emailService = emailService;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            var message = await _queueClient.ReceiveMessageAsync();
            if (message != null)
            {
                var request = JsonSerializer.Deserialize<EmailRequest>(message);
                await _emailService.SendEmailAsync(request);
            }
        }
    }
}
این کد یک سرویس پس‌زمینه را نشان می‌دهد که به‌صورت مداوم صف را بررسی می‌کند و در صورت وجود پیام، ایمیل را ارسال می‌کند. استفاده از BackgroundService در دات‌نت این امکان را فراهم می‌کند که کارگر به‌صورت مستقل و بدون وابستگی به رابط وب عمل کند.

مزایای الگوی وب-صف-کارگر
یکی از بزرگ‌ترین مزایای این الگو، مقیاس‌پذیری (Scalability) است. از آنجا که کارگرها مستقل از API وب عمل می‌کنند، می‌توان تعداد آن‌ها را بر اساس نیاز افزایش داد. برای مثال، اگر حجم پیام‌های صف افزایش یابد، افزودن کارگرهای بیشتر به سیستم می‌تواند بار را توزیع کند. این انعطاف‌پذیری به‌ویژه در برنامه‌هایی با ترافیک متغیر مفید است.
پاسخ‌گویی (Responsiveness) نیز از دیگر مزایای این الگو است. با سپردن وظایف زمان‌بر به کارگرها، رابط کاربری سریع‌تر به کاربران پاسخ می‌دهد، که تجربه کاربری بهتری را به ارمغان می‌آورد. همچنین، این الگو امکان مدیریت وظایف زمان‌بندی‌شده (Scheduled Jobs) مانند کارهای دوره‌ای (Cron Jobs) را فراهم می‌کند. برای مثال، می‌توان از همان سیستم صف برای ارسال خبرنامه‌های هفتگی یا پاک‌سازی داده‌های قدیمی استفاده کرد.

چالش‌ها و پیچیدگی‌ها
با وجود مزایای فراوان، این الگو بدون چالش نیست. یکی از مسائل اصلی، مدیریت خطاها (Error Handling) است. اگر کارگر در حین پردازش پیام با خطا مواجه شود، باید مکانیزمی برای بازآزمایی (Retry) یا انتقال پیام به یک صف خطا (Dead Letter Queue) وجود داشته باشد. برای مثال، Azure Service Bus قابلیت‌هایی مانند بازآزمایی خودکار و مدیریت پیام‌های ناموفق را ارائه می‌دهد.
یکی دیگر از چالش‌ها، تضمین یکپارچگی (Idempotency) است. اگر یک پیام به اشتباه چندین بار پردازش شود، ممکن است نتایج غیرمنتظره‌ای مانند ارسال چند ایمیل یکسان به کاربر ایجاد شود. برای جلوگیری از این مشکل، می‌توان از شناسه‌های یکتا (Unique Identifiers) در پیام‌ها استفاده کرد و قبل از پردازش، بررسی کرد که آیا پیام قبلاً پردازش شده است یا خیر.
پیچیدگی دیگر، نظارت و دیباگ (Monitoring and Debugging) است. از آنجا که پردازش در چندین مؤلفه توزیع شده است، ردیابی یک درخواست از ابتدا تا انتها ممکن است دشوار باشد. ابزارهایی مانند Application Insights در دات‌نت می‌توانند به ردیابی و ثبت وقایع (Logging) کمک کنند.

ارتباط با مفاهیم دیگر
الگوی وب-صف-کارگر شباهت‌هایی با معماری میکروسرویس‌ها (Microservices) دارد، اما نیازی به تقسیم کامل برنامه به سرویس‌های کوچک ندارد. در عوض، می‌توان از یک معماری یکپارچه (Monolithic) با مرزهای مشخص استفاده کرد، که پیچیدگی توسعه و استقرار را کاهش می‌دهد. این الگو همچنین با مفاهیمی مانند پردازش رویدادمحور (Event-Driven Processing) مرتبط است، جایی که پیام‌های صف به‌عنوان رویدادهایی در نظر گرفته می‌شوند که سیستم به آن‌ها واکنش نشان می‌دهد.
برای توسعه‌دهندگانی که با دات‌نت کار می‌کنند، این الگو می‌تواند با سایر ابزارهای مایکروسافت مانند Azure Functions یا Logic Apps ترکیب شود. برای مثال، Azure Functions می‌تواند به‌عنوان کارگر عمل کند و پیام‌های صف را پردازش کند، درحالی‌که API همچنان با ASP.NET Core اجرا می‌شود.

نتیجه‌گیری
الگوی وب-صف-کارگر یک رویکرد قدرتمند برای ساخت برنامه‌های وب مقیاس‌پذیر و پاسخ‌گو است. با جداسازی وظایف ناهمزمان و استفاده از سیستم صف، توسعه‌دهندگان می‌توانند تجربه کاربری بهتری ارائه دهند و در عین حال انعطاف‌پذیری سیستم را افزایش دهند. در اکوسیستم دات‌نت، ابزارهایی مانند ASP.NET Core و Azure Service Bus پیاده‌سازی این الگو را آسان‌تر کرده‌اند، اما موفقیت آن به مدیریت دقیق چالش‌هایی مانند خطاها و یکپارچگی بستگی دارد. با درک عمیق این الگو و استفاده از ابزارهای مناسب، توسعه‌دهندگان می‌توانند سیستم‌هایی طراحی کنند که نه‌تنها کارآمد باشند، بلکه برای آینده نیز آماده مقیاس‌پذیری باشند.


مشاهده مطلب اصلی

نظرات

  • امیر هاشم زاده در ۱۴۰۴/۰۲/۲۶ ۱۳:۴۶
    بعنوان یک نمونه عملیاتی در دنیای واقعی میشه به سامانه پل (پرداخت لحظه‌ای) و پل پی نام برد که درخواست از بانک مرکزی به بانک مقصد ارسال می‌شه و بلافاصله در صف قرار داده میشه و پاسخ فراخوان رو میدیم بعد درخواست توسط یک ورکر به هسته اصلی ارسال میشه هسته پردازش‌های لازم رو انجام میده و پاسخ رو برروی یک صف دیگه قرار میده و ورکر ما در بازه‌های زمانی بسیار کوتاه صف رو چک میکنه و پاسخ‌ها رو به بانک مرکزی ارسال میکنه البته این تصویر کلی‌ش بود و جزییات دیگه‌ای مانند تعداد تلاش‌ها برای پاسخ‌های ارسال نشده، استراتژی تعیین تکلیف تراکنش در زمان‌‎های اخلال سامانه و .... وجود داره که باید تمام جریان‌ها (فلو) با دقت بررسی بشه که همپوشانی با هم نداشته باشند.
    • وحید نصیری در ۱۴۰۴/۰۲/۲۷ ۱۲:۲۹
      یک نمونه کوچک همین الگو در سایت جاری در حال استفاده‌است. در کتابخانه‌ی «DNTCommon.Web.Core» قابلیتی تحت عنوان IBackgroundQueueService پیش بینی شده که اگر مراحل راه اندازی این کتابخانه را طی کنید، این سرویس هم اکنون در اختیار شما است. با استفاده از آن می‌شود یک کار را به‌صورت خودکار در صف انجام کارهای پس‌زمینه‌ای که توسط همین کتابخانه مدیریت می‌شود، قرار داد. چند نمونه، استفاده از آن در سایت جاری:
      • استفاده از آن برای ثبت اطلاعات بازدید کنندگان. مزیت این روش، عدم از کار افتادن سایت، با بالارفتن تعداد بازدیدهای همزمان است. چون کار پردازشی آن در ترد اصلی درخواست‌ها انجام نمی‌شود و آهسته و پیوسته به صف ثبت و بررسی پشت صحنه‌ی آن واگذار می‌شود (بدون مسدود شدن ترد اصلی برنامه).
      • ثبت اطلاعات لاگ‌ها و خطاهای برنامه. ثبت این‌ لاگ‌ها هم به صف پردازشی پشت صحنه واگذار می‌شود چون تعداد لاگ‌های برنامه ممکن است به علت خطاهایی که بات‌ها ایجاد می‌کنند، بالا باشد (از خطاهای 404 تا بررسی‌های امنیتی که توسط یکسری بات‌های مخصوص، به صورت مداوم و با سرعت بالا انجام می‌شوند).
      • ارسال تمام ایمیل‌های برنامه. سرویس ارسال ایمیل برنامه طوری طراحی شده که اگر مطلبی، پیامی و یا خطایی و یا خبرنامه‌ای نیاز به ارسال داشت، ترد جاری درخواست، قفل نشود و این پیام به صف پشت صحنه‌ای جهت ارسال منتقل شود. به این صورت، سرعت ثبت اطلاعات در سایت بسیار بالا می‌رود. فرض کنید می‌خواهید نظری را در سایت ثبت کنید. یک قسمت آن ارسال ایمیل به نویسنده و مدیران سایت است. این قسمت دوم، نیازی نیست در ترد درخواست جاری مدیریت شود و به این صورت به صف پشت صحنه منتقل می‌شود. انتقال اطلاعات به صف پشت صحنه، بسیار سریع است و مدیریت این ایمیل‌ها، آهسته و پیوسته در تردی دیگر انجام می‌شود.