Проблема массового обновления остатков товаров и нагрузка на IndexNow
В крупных магазинах WooCommerce при массовом изменении остатков товаров (например, после синхронизации с поставщиками) возникает необходимость быстро и корректно отправить обновленные URL товаров в поисковые системы через IndexNow. Прямая отправка каждого URL по отдельности приводит к избыточным HTTP-запросам, задержкам и возможным ошибкам из-за ограничений API. Поэтому нужна оптимизация очереди и пакетная обработка URL.
Диагностика проблем с отправкой URL при массовых обновлениях
- Проверить логи ошибок IndexNow (если ведутся) или включить отладку запросов.
- Отследить время отклика при отправке URL и количество параллельных запросов.
- Использовать инструмент мониторинга сервера для выявления пиков нагрузки.
- Проверить, не превышается ли лимит частоты запросов API IndexNow.
Шаги по реализации оптимальной очереди и пакетной отправки URL в WooCommerce
1. Создание хранилища очереди URL в базе данных
Используем пользовательскую таблицу или опцию с сериализованным массивом для хранения URL, которые нужно отправить.
global $wpdb;
$table_name = $wpdb->prefix . 'indexnow_queue';
// Создать таблицу при активации плагина
function create_indexnow_queue_table() {
global $wpdb, $table_name;
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
url VARCHAR(255) NOT NULL,
status ENUM('pending', 'sent', 'error') NOT NULL DEFAULT 'pending',
last_attempt DATETIME DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY url (url)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
register_activation_hook(__FILE__, 'create_indexnow_queue_table');2. Добавление URL в очередь при массовом обновлении запасов
Подключаемся к хуку обновления запасов WooCommerce и добавляем URL товара в очередь.
add_action('woocommerce_update_product_stock', 'enqueue_indexnow_url_on_stock_update', 10, 1);
function enqueue_indexnow_url_on_stock_update($product) {
global $wpdb, $table_name;
$url = get_permalink($product->get_id());
if (!$url) return;
$exists = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $table_name WHERE url = %s", $url));
if (!$exists) {
$wpdb->insert($table_name, ['url' => $url, 'status' => 'pending']);
}
}3. Регулярная пакетная отправка URL через WP-Cron
Создаем периодическое событие для отправки пакетов URL, например по 50 штук за раз.
if (!wp_next_scheduled('indexnow_send_batch')) {
wp_schedule_event(time(), 'five_minutes', 'indexnow_send_batch');
}
add_action('indexnow_send_batch', 'send_indexnow_url_batch');
function send_indexnow_url_batch() {
global $wpdb, $table_name;
$batch_size = 50;
$pending_urls = $wpdb->get_results("SELECT * FROM $table_name WHERE status = 'pending' ORDER BY id ASC LIMIT $batch_size");
if (empty($pending_urls)) return;
$urls_to_send = wp_list_pluck($pending_urls, 'url');
$endpoint = 'https://api.indexnow.org/indexnow';
$api_key = 'ВАШ_КЛЮЧ_API';
$payload = json_encode(['host' => parse_url(home_url(), PHP_URL_HOST), 'key' => $api_key, 'keyLocation' => home_url('/indexnow-key.txt'), 'urlList' => $urls_to_send]);
$response = wp_remote_post($endpoint, [
'body' => $payload,
'headers' => ['Content-Type' => 'application/json'],
'timeout' => 15,
]);
if (is_wp_error($response) || wp_remote_retrieve_response_code($response) != 200) {
foreach ($pending_urls as $url_item) {
$wpdb->update($table_name, ['status' => 'error', 'last_attempt' => current_time('mysql')], ['id' => $url_item->id]);
}
} else {
foreach ($pending_urls as $url_item) {
$wpdb->update($table_name, ['status' => 'sent', 'last_attempt' => current_time('mysql')], ['id' => $url_item->id]);
}
}
}Проверка результата после внедрения
- В базе данных таблица
indexnow_queueдолжна показывать статусsentдля обработанных URL. - В логах сервера или в отладке WP Remote Post проверить успешные ответы от API IndexNow.
- С помощью инструментов поисковиков или IndexNow API проверить, что изменения по URL фактически приняты.
- Отслеживать нагрузку на сервер и время обработки обновлений, оно должно уменьшиться.
Частые ошибки и способы исправления
- Дублирование URL в очереди: Проверьте уникальность URL при вставке, используйте уникальный индекс в базе.
- Перегрузка WP-Cron: Увеличьте интервал запуска или используйте системный cron для стабильности.
- Ошибка 429 (Too Many Requests): Уменьшите размер пакета, добавьте задержки между запросами.
- Не обновляются статусы URL: Проверьте права базы данных и корректность запросов на обновление.
Практические советы по безопасности и производительности
- Храните API ключ в
wp-config.phpили в защищенной опции с шифрованием. - Ограничьте количество одновременных запросов к IndexNow, чтобы избежать блокировок.
- Применяйте транзиенты или кеширование для частых запросов к базе, чтобы снизить нагрузку.
- Используйте системный cron вместо WP-Cron на больших магазинах для более надежной работы.
Сравнение способов реализации очереди в WooCommerce для IndexNow
| Метод | Плюсы | Минусы |
|---|---|---|
| Пользовательская таблица | Гибкость, быстрый доступ, легко масштабируется | Требует создания и поддержки структуры БД |
| Опция с сериализованным массивом | Простота реализации, не требует таблиц | Проблемы с масштабом и конкуренцией при большом объеме URL |
| Транзиенты | Автоматическое удаление, встроенный кеш WP | Не подходит для долговременного хранения и больших объемов |