Background Processing در وردپرس یعنی اجرای عملیات سنگین در فرآیندهای مستقل از چرخه درخواست HTTP، به‌گونه‌ای که پاسخ به کاربر هرگز منتظر تکمیل آن نماند.

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

سه جزء اصلی در این معماری وجود دارد: صف تسک، Worker اجرایی و محرک دوره‌ای که Worker را فعال نگه می‌دارد.

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

بدون طراحی درست چرخه حیات Worker و مدیریت حافظه، Background Processing می‌تواند به منبع نشت منابع و کندی مزمن در سایت تبدیل شود.

در یکی از پروژه‌های گذشته، تولید گزارش ماهانه فروش هر بار سرور را برای چند دقیقه از پا می‌انداخت. انتقال همان عملیات به یک Worker پس‌زمینه، نه‌فقط مشکل را حل کرد، بلکه پایداری سایت را در بازه‌های گزارش‌گیری به سطح دیگری برد. آن تجربه، آغازی بود برای جدی‌گرفتن Background Processing به‌عنوان یک لایه معماری، نه یک تنظیم حاشیه‌ای.

Background Processing دقیقاً چه مسئله‌ای را حل می‌کند

Background Processing (Background process) یک الگوی معماری است که در آن، عملیات‌هایی که پاسخ فوری آن‌ها برای کاربر ضروری نیست، در فرآیندی جداگانه و مستقل اجرا می‌شوند. این جداسازی، از مسیر بحرانی پاسخ کاربر حذف می‌شود و بار را به یک زیرساخت مدیریت‌شده منتقل می‌کند.

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

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

Background Processing دقیقاً همین جابه‌جایی را انجام می‌دهد. عملیات را از مسیر پاسخ حذف می‌کند و آن را به یک مسیر مستقل منتقل می‌کند که می‌تواند به‌طور مستقل مدیریت، پایش و مقیاس‌دهی شود. اثر این انتقال، هم روی زمان پاسخ و هم روی ظرفیت سرور دیده می‌شود.

در پروژه‌های بزرگ، این جداسازی به یک ضرورت تبدیل می‌شود. بدون آن، هر عملیات سنگین می‌تواند نقطه گلوگاه کل سایت باشد و هر خطای موقت می‌تواند تجربه کاربر را مختل کند. کاربرد کامل این الگو در چارچوب کلی بهینه‌سازی سرور برای وردپرس به‌عنوان یکی از مؤثرترین مسیرهای بهبود شناخته می‌شود.

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

مرز با Async Tasks و WP-Cron

Background Processing با Async Task و WP-Cron هم‌ریشه است اما یکسان نیست. تفکیک این سه مفهوم، پیش‌نیاز تصمیم‌گیری درست است.

Async Task یک عملیات مشخص است که در زمانی متفاوت از درخواست اصلی اجرا می‌شود. تمرکز این مفهوم روی خود عملیات است: چه چیزی اجرا می‌شود و چه زمانی. مکانیزم‌های رایج آن شامل درخواست‌های Loopback، Endpoint های REST و صف‌های سبک است. تصویر جامع این حوزه در Async Tasks در وردپرس به‌تفصیل آمده است.

WP-Cron یک مکانیزم زمان‌بندی است که تسک‌های موعد‌رسیده را در زمان بازدید کاربران اجرا می‌کند. تمرکز این مکانیزم روی زمان‌بندی است، نه روی معماری اجرا. محدودیت‌های آن، از جمله وابستگی به بازدید کاربران و اجرای تسک در همان درخواست، در کرون وردپرس و زمان‌بندی خودکار کارها بررسی شده است.

Background Processing در سطح بالاتری از این دو قرار می‌گیرد. تمرکز آن روی معماری است: چگونه صف مدیریت می‌شود، چگونه Worker اجرا می‌شود، چگونه چرخه حیات آن کنترل می‌شود و چگونه در زمان خطا بازیابی می‌شود. Async Task و WP-Cron می‌توانند اجزایی از یک سیستم Background Processing باشند، اما خود سیستم چیز دیگری است.

در عمل، یک معماری کامل Background Processing شامل هر سه سطح است: یک صف برای نگه‌داشتن تسک‌ها، یک یا چند Worker برای اجرای آن‌ها و یک محرک دوره‌ای که Worker را فعال نگه می‌دارد. بدون یکی از این سه، معماری ناقص می‌ماند.

معماری پایه: صف، Worker، محرک

یک سیستم Background Processing در وردپرس از سه جزء اصلی ساخته شده است که هر یک نقش مشخصی دارند.

جزء اول صف است. صف یک ساختار داده است که تسک‌های در انتظار اجرا را نگه می‌دارد. هر تسک، مجموعه‌ای از پارامترها و وضعیت است: در انتظار، در حال اجرا، تکمیل‌شده یا شکست‌خورده. صف می‌تواند در جدول اختصاصی پایگاه داده، در Redis، در یک سیستم پیام‌رسان خارجی یا حتی در فایل‌های موقت پیاده شود.

جزء دوم Worker است. Worker یک فرآیند اجرایی است که به‌طور مداوم یا دوره‌ای صف را بررسی می‌کند و تسک‌های در انتظار را اجرا می‌کند. هر Worker، معمولاً یک یا چند تسک را در هر چرخه برمی‌دارد، اجرا می‌کند و نتیجه را ثبت می‌کند.

جزء سوم محرک است. محرک یک مکانیزم است که Worker را فعال می‌کند. در ساده‌ترین حالت، این محرک می‌تواند WP-Cron باشد. در حالت پیچیده‌تر، یک Cron واقعی روی سیستم‌عامل یا یک فرآیند دائمی با Supervisor یا Systemd است.

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

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

کتابخانه WP_Background_Process و الگوی آن

کتابخانه WP_Background_Process یکی از شناخته‌شده‌ترین ابزارهای Background Processing در اکوسیستم وردپرس است. این کتابخانه در ابتدا برای ووکامرس توسعه داده شد و بعدها به‌عنوان یک کتابخانه مستقل در دسترس قرار گرفت.

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

class WPK_Order_Sync extends WP_Background_Process {

    protected $action = "wpk_order_sync";

    protected function task( $item ) {
        $order_id = absint( $item["order_id"] );
        if ( ! $order_id ) {
            return false;
        }
        $order = wc_get_order( $order_id );
        if ( ! $order ) {
            return false;
        }
        wpk_push_order_to_external( $order );
        return false;
    }

    protected function complete() {
        parent::complete();
        update_option( "wpk_last_sync_time", time() );
    }
}

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

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

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

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

صف بدون مکانیزم محدودسازی، یک بمب ساعتی است؛ انباشت آرام تسک‌ها دیر یا زود به بحران تبدیل می‌شود.

چرخه حیات یک Worker در وردپرس

درک چرخه حیات Worker، پیش‌نیاز طراحی درست یک سیستم Background Processing است. هر Worker از لحظه فعال‌سازی تا پایان اجرا، چند مرحله مشخص را طی می‌کند.

مرحله اول، فعال‌سازی است. Worker با فراخوانی یک تابع یا یک درخواست HTTP فعال می‌شود. در این مرحله، منابع لازم تخصیص می‌یابند و اتصال‌ها به صف برقرار می‌شوند.

مرحله دوم، بارگذاری تسک است. Worker یک یا چند تسک از صف برمی‌دارد و آن‌ها را در حافظه بارگذاری می‌کند. این مرحله باید با محدودیت انجام شود تا در صورت وجود تسک سنگین، حافظه سرور اشباع نشود.

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

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

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

نکته مهم این است که اگر Worker به‌درستی چرخه خود را طی نکند، نشت منابع می‌تواند رخ دهد. یک Worker با نشتی حافظه، در طول زمان می‌تواند مصرف منابع را چند برابر کند. این مسئله در سرورهایی که تنظیم PHP-FPM برای وردپرس در آن‌ها فعال است، می‌تواند به کندی سراسری منجر شود.

همزمانی، قفل‌گذاری و ترتیب اجرا

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

مکانیزم استاندارد برای جلوگیری از این مشکل، قفل‌گذاری (Locking) است. با استفاده از یک قفل، تنها یک Worker می‌تواند در هر لحظه یک تسک مشخص را بردارد. Workerهای دیگر منتظر می‌مانند تا قفل آزاد شود.

function wpk_acquire_lock( $key, $timeout = 30 ) {
    $option = "wpk_lock_" . md5( $key );
    $now    = time();

    if ( $existing = get_option( $option ) ) {
        if ( $existing["expires"] > $now ) {
            return false;
        }
    }
    update_option( $option, array(
        "owner"    => wpk_worker_id(),
        "expires"  => $now + $timeout,
    ), false );
    return true;
}

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

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

ترتیب اجرای تسک‌ها نیز اهمیت دارد. اگر برخی تسک‌ها به یکدیگر وابسته باشند، ترتیب اجرا باید تضمین شود. ساده‌ترین رویکرد، پیاده‌سازی صف به‌صورت FIFO (First In First Out) است، اما در سناریوهای پیچیده‌تر، پیاده‌سازی صف اولویت‌دار ممکن است لازم شود.

Batch Processing و مدیریت حافظه

Batch Processing یعنی پردازش تسک‌ها در دسته‌های کوچک، به‌جای پردازش همه تسک‌ها در یک اجرا. این الگو، استاندارد پیاده‌سازی سیستم‌های Background Processing است و دلایل مشخصی دارد.

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

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

دلیل سوم، امکان توزیع بار است. اگر چند Worker همزمان فعال باشند، هر یک می‌تواند یک دسته از تسک‌ها را بردارد و بار بین آن‌ها توزیع شود.

class WPK_Batch_Worker {

    const BATCH_SIZE = 50;

    public function run() {
        while ( $tasks = $this->fetch_next_batch() ) {
            foreach ( $tasks as $task ) {
                $this->process_task( $task );
            }
            $this->commit_batch( $tasks );
            $this->maybe_release_memory();
        }
    }

    private function maybe_release_memory() {
        if ( memory_get_usage() > 200 * 1024 * 1024 ) {
            gc_collect_cycles();
        }
    }
}

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

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

در پروژه‌هایی که با داده‌های حجیم کار می‌کنند، ترکیب Batch Processing با بهینه‌سازی کوئری‌های پایگاه داده ضروری است. اگر پردازش هر دسته به کوئری‌های کند منجر شود، مزیت Batch Processing کم می‌شود. رعایت اصول کلی در بهینه‌سازی کوئری‌های MySQL در اینجا مستقیماً کاربرد دارد.

Worker پیوسته در برابر Worker دوره‌ای

دو مدل اصلی برای اجرای Worker وجود دارد که هر یک شرایط استفاده مختص خود را دارد.

مدل اول، Worker پیوسته است. در این مدل، یک فرآیند به‌طور مداوم اجرا می‌شود و صف را بررسی می‌کند. این مدل، تأخیر کمتری دارد چون تسک‌ها بلافاصله پس از ورود به صف اجرا می‌شوند.

مدل دوم، Worker دوره‌ای است. در این مدل، یک محرک (Cron واقعی یا WP-Cron) در بازه‌های مشخص، Worker را فعال می‌کند. Worker یک یا چند دسته تسک را پردازش می‌کند و سپس پایان می‌یابد.

مدل پیوسته مزیت سرعت دارد اما نیازمند زیرساخت پایدار و ابزارهایی مانند Supervisor یا Systemd است که فرآیند را در زمان خطا دوباره راه‌اندازی کنند. مدل دوره‌ای ساده‌تر است اما تأخیر بیشتری دارد و برای تسک‌های حساس به زمان مناسب نیست.

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

در ترکیب با معماری چندسروری، مدل پیوسته پیچیدگی بیشتری ایجاد می‌کند، چون هماهنگی بین Workerهای چند سرور نیازمند یک صف مشترک است. راهنمایی‌های عملی در این حوزه در مدیریت سرور چیست و وظایف آن آمده است.

Cron واقعی به‌عنوان محرک مستقل

محرک مستقل، قلب یک سیستم Background Processing قابل اعتماد است. در وردپرس، پیش‌فرض WP-Cron برای این نقش مناسب نیست، چون به بازدید کاربران وابسته است و تسک‌ها را در همان درخواست اجرا می‌کند.

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

# Disable default WP-Cron in wp-config.php
define( "DISABLE_WP_CRON", true );

# Add a real system cron job
# /etc/cron.d/wp-cron
*/2 * * * * www-data /usr/bin/php /var/www/html/wp-cron.php >/dev/null 2>&1

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

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

#!/usr/bin/env bash
LOCKFILE=/var/lock/wp-cron.lock

if [ -e $LOCKFILE ]; then
    exit 0
fi

touch $LOCKFILE
trap "rm -f $LOCKFILE" EXIT

/usr/bin/php /var/www/html/wp-cron.php

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

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

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

کاربردها در فروشگاه ووکامرس

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

پس از ثبت سفارش، چندین عملیات باید انجام شود: ارسال ایمیل تأییدیه، اطلاع به سیستم انبار، کاهش موجودی، همگام‌سازی با سیستم حسابداری و ثبت رویداد در ابزارهای تحلیلی. اگر همه این عملیات به‌طور همگام اجرا شوند، کاربر چند ثانیه منتظر می‌ماند.

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

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

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

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

بهینه‌سازی کامل فروشگاه ووکامرس در این لایه، بخشی از یک مسیر منسجم است که در بهینه‌سازی سرعت ووکامرس به‌تفصیل آمده است. Background Processing یکی از مؤثرترین اجزای این مسیر است، چون بار سنگین‌ترین عملیات‌ها را از مسیر کاربر حذف می‌کند.

پیامدهای امنیتی و کنترل دسترسی

Background Processing یک سطح حمله جدید در معماری سایت ایجاد می‌کند که باید به‌طور صریح مدیریت شود. اگر Endpointهای غیرهمگام یا محرک‌های Worker به‌درستی محافظت نشوند، امکان سوءاستفاده از آن‌ها برای اشباع سرور یا اجرای عملیات ناخواسته فراهم می‌شود.

سه سطح امنیتی وجود دارد که باید در طراحی لحاظ شوند. سطح اول، احراز هویت محرک است. اگر Worker از طریق HTTP فعال می‌شود، این درخواست باید با یک توکن یا امضای مشخص تأیید شود. درخواست‌های بدون این تأیید باید رد شوند.

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

سطح سوم، محدودسازی دسترسی به صف است. اگر صف در جدول تنظیمات وردپرس نگه داشته می‌شود، دسترسی به آن باید محدود باشد. اگر صف در Redis یا سیستم خارجی است، دسترسی به آن باید با احراز هویت محافظت شود.

add_action( "rest_api_init", function () {
    register_rest_route( "wpk/v1", "/run-worker", array(
        "methods"             => "POST",
        "callback"            => "wpk_run_worker_endpoint",
        "permission_callback" => function ( $request ) {
            $token = $request->get_header( "X-WPK-Worker-Token" );
            $valid = get_option( "wpk_worker_token" );
            if ( ! $token || ! $valid || ! hash_equals( $valid, $token ) ) {
                return new WP_Error( "forbidden", "Invalid token", array( "status" => 403 ) );
            }
            return true;
        },
    ) );
} );

این الگو، دسترسی به Endpoint اجرای Worker را محدود به درخواست‌های دارای توکن معتبر می‌کند. استفاده از hash_equals به‌جای مقایسه ساده، از حملات زمان‌بندی جلوگیری می‌کند.

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

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

پایش، لاگ و اشکال‌زدایی

پایش یک سیستم Background Processing نیازمند سه سطح اندازه‌گیری است. بدون این سطوح، مشکلات این لایه می‌توانند مدت‌ها پنهان بمانند.

سطح اول، پایش صف است. سه عدد کلیدی باید اندازه‌گیری شوند: تعداد تسک‌های در انتظار، تعداد تسک‌های در حال اجرا و تعداد تسک‌های شکست‌خورده. انباشت تسک‌های در انتظار، نشانه ظرفیت ناکافی Worker است.

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

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

function wpk_log_task_result( $task_id, $status, $duration, $error = null ) {
    $entry = array(
        "task_id"  => $task_id,
        "status"   => $status,
        "duration" => $duration,
        "time"     => time(),
        "error"    => $error,
    );
    $log = get_option( "wpk_task_log", array() );
    $log[] = $entry;
    if ( count( $log ) > 1000 ) {
        $log = array_slice( $log, -500 );
    }
    update_option( "wpk_task_log", $log, false );
}

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

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

در سمت جریان استقرار، تغییرات کد باید Workerها را هم به‌روز کنند. اگر Worker قدیمی در حال اجرا باشد و کد جدید مستقر شود، می‌تواند به تعارض منجر شود. راه‌حل استاندارد، توقف Workerها، استقرار کد جدید و راه‌اندازی مجدد آن‌ها است. اصول این جریان در پیاده‌سازی CI/CD برای پروژه‌های وردپرسی به‌تفصیل آمده است.

جدول تصمیم‌گیری معماری Background Processing

سناریومدل Workerمحرکریسک اصلی
سایت کوچک با تسک‌های دوره‌ایدوره‌ایWP-Cron + Cron واقعیتأخیر در اجرای تسک‌ها
سایت متوسط با تسک‌های پراکندهدوره‌ایAction Scheduler + Cron واقعیانباشت صف در ساعات اوج
فروشگاه پربازدیدترکیبیCron + Loopbackهمزمانی در ثبت سفارش
پلتفرم چندسروریپیوستهSupervisor + صف مشترکهزینه زیرساخت و پیچیدگی

اشتباهات رایج

نخستین اشتباه، اجرای Background Processing بدون محرک مستقل است. اگر محرک فقط WP-Cron پیش‌فرض باشد، Worker در زمان‌های نامنظم و وابسته به بازدید کاربران فعال می‌شود. نتیجه، تأخیر غیرقابل پیش‌بینی در اجرای تسک‌ها.

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

سومین اشتباه، نادیده گرفتن مدیریت حافظه در Workerهای طولانی است. یک Worker با نشتی حافظه می‌تواند در طول چند ساعت به مصرف حافظه‌ای چند برابر برسد و سرور را از پا بیندازد. اثری مشابه این الگو در رفع مصرف بالای CPU در وردپرس به‌عنوان یک پدیده تکرارشونده دیده می‌شود.

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

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

ششمین اشتباه، نادیده گرفتن امنیت Endpointهای فعال‌سازی Worker است. اگر این Endpointها محافظت نشوند، امکان اشباع سرور با درخواست‌های متعدد فراهم می‌شود. رعایت اصول مشابه آنچه در امن‌سازی ورود ادمین وردپرس آمده، در این لایه نیز ضروری است.

هفتمین اشتباه، بی‌توجهی به بار پایگاه داده در زمان اجرای Workerهاست. اگر چند Worker همزمان کوئری‌های سنگین اجرا کنند، بار پایگاه داده افزایش می‌یابد و می‌تواند به کندی سراسری منجر شود. رعایت اصول بهینه‌سازی در بهینه‌سازی پیشرفته دیتابیس وردپرس در این لایه مستقیماً کاربرد دارد.

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

پرسش‌های پرتکرار درباره Background Processing در وردپرس

تفاوت Background Processing و Async Task چیست؟

Async Task به یک عملیات مشخص اشاره دارد که در زمانی متفاوت از درخواست اصلی اجرا می‌شود. Background Processing یک معماری کامل است که شامل صف، Worker و محرک است. Async Task می‌تواند بخشی از یک سیستم Background Processing باشد، اما خودش آن سیستم نیست.

آیا WP-Cron برای Background Processing کافی است؟

برای سایت‌های کوچک با تسک‌های سبک، WP-Cron با یک Cron واقعی روی سرور می‌تواند کافی باشد. برای سایت‌های متوسط و بزرگ، نیاز به یک صف تخصصی و Worker مدیریت‌شده است که WP-Cron به‌تنهایی از عهده آن برنمی‌آید.

چه زمانی باید از WP_Background_Process استفاده کرد؟

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

چرا تسک‌های پس‌زمینه در صف می‌مانند و اجرا نمی‌شوند؟

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

چگونه از اجرای همزمان یک تسک جلوگیری کنم؟

با استفاده از مکانیزم قفل‌گذاری. هر تسک پیش از اجرا، یک قفل در صف یا در یک سیستم کش مشترک ثبت می‌کند. اگر قفل موجود باشد، Worker دیگری نمی‌تواند همان تسک را بردارد.

آیا Background Processing روی امنیت سایت اثر دارد؟

بله، اگر Endpointهای فعال‌سازی Worker به‌درستی محافظت نشوند. احراز هویت با توکن، محدودسازی نرخ درخواست و چرخش دوره‌ای توکن، سه اقدام ضروری در این حوزه هستند.

آیا Background Processing جایگزین بهینه‌سازی کد است؟

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

چگونه تسک‌های شکست‌خورده را مدیریت کنم؟

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

آیا Background Processing روی سئو اثر دارد؟

اثر مستقیم ندارد، اما اثر غیرمستقیم آن جدی است. کاهش زمان پاسخ، پایداری سایت در بار بالا و جلوگیری از شکست عملیات، همه به تجربه کاربر کمک می‌کنند و این تجربه در رتبه‌بندی اثر دارد.

چه زمانی به Worker پیوسته نیاز است؟

زمانی که حجم تسک‌ها بالا و پیوسته باشد یا تسک‌ها حساس به زمان باشند. Worker پیوسته تأخیر کمتری دارد اما نیازمند زیرساخت پایدار و ابزارهایی مانند Supervisor برای مدیریت فرآیند است.

آیا Background Processing روی مصرف منابع سرور اثر منفی دارد؟

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

آیا Background Processing برای همه پروژه‌های وردپرسی لازم است؟

برای سایت‌های کوچک با تسک‌های سبک، ممکن است ضروری نباشد. برای سایت‌های متوسط و بزرگ، به‌ویژه فروشگاه‌ها و پلتفرم‌های محتوایی، Background Processing یکی از پایه‌های معماری است.

یک نکته برای ادامه مسیر

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

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