WordPress: Блокировка Cron и Очередь

Вопрос или проблема

У меня есть несколько скриптов, требующих больших ресурсов ЦП, которые я не хочу запускать одновременно. Время от времени скрипты пересекаются и вызывают сбой сервера. Уже при 2 ГБ контейнер MySQL все еще аварийно завершает работу.

У меня настроен cron, который запускает example.com/cron.php?do_cron=randstr каждые 15 минут.

Есть ли способ установить блокировку и запускать только одну задачу cron за раз? Когда она завершится, следующая задача должна запуститься.

Я знаю, что этого можно достичь с помощью механизма блокировок файлов PHP (но в этом случае следующая задача не ставится в очередь). Не уверен, делает ли WP это самостоятельно.

Любая помощь будет оценена!

Простой Cronjob Walker

  1. Создайте CPT cronjob для ваших cronjob’ов.
  2. Добавьте соответствующие метаданные поста (действие, last_executed и все, что вам нужно)
  3. Создайте функцию walker

    function my_cronjob_walker() {
        $args= array(
            'post_type' => 'cronjob',
            'posts_per_page' => 1,
            'meta_key' => 'last_executed',
            'orderby' => 'meta_value',
        );
        $cronjob = new WP_Query($args);
        if ($cronjob->have_posts()) while ($cronjob->have_posts()) {
            $cronjob->the_post();
            // выполняйте ваши задачи cron здесь
            do_action(get_post_meta(get_the_ID(), 'action', true));
            update_post_meta(get_the_ID(), 'last_executed', date('c'));
        }
    }
    if ( ! wp_next_scheduled( 'do_cronjob_walker' ) ) {
        wp_schedule_event( time(), 'hourly', 'do_cronjob_walker' );
    }
    
    add_action( 'do_cronjob_walker', 'my_cronjob_walker' );
    

Ответ или решение

Оптимизация Cron-задач в WordPress: Блокировка и Очередь

Ваша задача по выполнению интенсивных скриптов в WordPress без одновременного их выполнения может быть решена несколькими способами. Ниже представлено подробное описание, как гарантировать, что эти задачи будут выполняться последовательно, а не одновременно, что приведет к сбоям и перегрузкам сервера.

Проблема, с которой вы столкнулись

Как указано в вашем вопросе, вы используете crontab для запуска скрипта cron.php каждые 15 минут. Однако из-за интенсивности ваших скриптов возможно их перекрытие, что приводит к перегрузке системы и сбоям, особенно в вашем случае, где используется контейнер MySQL с ограниченным объемом памяти.

Решение с использованием блокировки

WordPress предоставляет механизмы обработки задач с использованием WP-Cron, но при этом не всегда гарантируется последовательность выполнения. Для решения вашей проблемы можно использовать механизмы блокировки и очереди.

  1. Создание пользовательского типа записи (CPT) для Cron-задач:
    Создайте CPT с названием cronjob, который будет хранить ваши задачи cron вместе с метаданными, такими как последнее время выполнения и действие, которое необходимо выполнить.

    function create_cronjob_cpt() {
       register_post_type('cronjob', array(
           'labels' => array('name' => __('Cronjobs')),
           'public' => false,
           'has_archive' => false,
           'supports' => array('title'),
       ));
    }
    add_action('init', 'create_cronjob_cpt');
  2. Добавление и обновление метаданных:
    При добавлении записи в тип cronjob, укажите необходимое действие и время последнего выполнения.

    function add_cronjob($action) {
       $post_id = wp_insert_post(array(
           'post_type' => 'cronjob',
           'post_title' => 'Cronjob for ' . $action,
           'post_status' => 'publish',
       ));
       update_post_meta($post_id, 'action', $action);
       update_post_meta($post_id, 'last_executed', null);
    }
  3. Создание функции для обработки задач (Walker):
    Используйте функцию, которая будет вызывать только одну задачу крона за раз, блокируя выполнение следующих задач до завершения текущей.

    function my_cronjob_walker() {
       $args= array(
           'post_type' => 'cronjob',
           'posts_per_page' => 1,
           'meta_key' => 'last_executed',
           'orderby' => 'meta_value',
           'order' => 'ASC',
       );
       $cronjob = new WP_Query($args);
    
       if ($cronjob->have_posts()) {
           while ($cronjob->have_posts()) {
               $cronjob->the_post();
               // Выполнение вашей cron задачи
               do_action(get_post_meta(get_the_ID(), 'action', true));
               update_post_meta(get_the_ID(), 'last_executed', date('c'));
           }
           wp_reset_postdata(); // Обязательно сбрасываем данные после цикла
       }
    }
    
    if ( ! wp_next_scheduled( 'do_cronjob_walker' ) ) {
       wp_schedule_event(time(), 'hourly', 'do_cronjob_walker');
    }
    
    add_action('do_cronjob_walker', 'my_cronjob_walker');

Заключение

Приведенные выше шаги обеспечивают последовательное выполнение ваших cron-задач в WordPress и предотвращают их одновременное выполнение, что сэкономит ресурсы вашего сервера и минимизирует риск его перегрузки. Этот подход позволит вам эффективно и надежно управлять вашими скриптами.

Для улучшения производительности не забывайте регулярно проверять и оптимизировать ваши SQL-запросы и использовать кэширование, чтобы минимизировать нагрузку на базу данных. Также стоит рассмотреть возможность запуска таких задач в более позднее время, когда нагрузка на сервер минимальна.

SEO-Оптимизация

Для повышения видимости данной информации при поисковых запросах, используйте ключевые слова и фразы, такие как "WordPress cron задачи", "последовательное выполнение cron задач в WordPress" и "блокировка cron задач WordPress".

Следуя этим шагам, вы сможете не только устранить проблему, но и обеспечить ровную работу вашего веб-приложения на платформе WordPress.

Оцените материал
Добавить комментарий

Капча загружается...