Как работает пакетный API внутри?


19

Я столкнулся с проблемой тайм-аута, используя миграцию на днях и начал задаваться вопросом, как Batch API работает внутри.

Насколько я понимаю, в простейшей форме вы передадите массив значений (например, nids) и функцию для работы с этими значениями. Затем пакетный API обрабатывает фиксированное число этих значений с каждым запросом до его завершения.

Когда пакет запускается, кажется, что страница использует Ajax-запросы, чтобы показать ход выполнения пакетной операции (% выполнено и сообщения). Я предполагаю, что он ждет, пока запрос не завершится, чтобы обновить ход выполнения, а затем сразу же после этого начать следующий запрос?

Если страница с пакетным запросом закрыта, останавливается ли пакетная обработка? Будет ли он перезапущен, когда тот же URL открывается снова? Модуль переноса иногда продолжается, но, вероятно, он использует очереди?

Ответы:


40

Вот как работает пакет (на основании моего понимания)

1. Инициализировать

  1. Инициализируйте пакетную обработку. На основе конфигурации клиентов (браузеров) о том, включен JavaScript или нет.
  2. Клиенты с поддержкой JavaScript идентифицируются с помощью файла cookie has_js, установленного в drupal.js. Если ни одна страница с поддержкой JavaScript не была посещена во время сеанса браузера текущего пользователя, возвращается не-JavaScript версия.
  3. Если JavaScript включен, пакетный запрос использует ajax, чтобы поддерживать соединение в течение всего запроса.
  4. Если JavaScript не включен, Пакетное использование устанавливает метатег в html для создания регулярных интервалов обновления, чтобы поддерживать соединение в течение всего запроса.

(Вот как обновляется индикатор выполнения выполнения задания.)

Пакетный процесс

  1. Для запуска процесса Batch создает очередь и добавляет все операции (функции и аргументы), которые вы определяете в массиве пакета, например:

    $batch = array (
    'operations' => array(
      array('batch_example_process', array($options1, $options2)),
      array('batch_example_process', array($options3, $options4)),
      ),
    'finished' => 'batch_example_finished',
    'title' => t('Processing Example Batch'),
    'init_message' => t('Example Batch is starting.'),
    'progress_message' => t('Processed @current out of @total.'),
    'error_message' => t('Example Batch has encountered an error.'),
    'file' => drupal_get_path('module', 'batch_example') . '/batch_example.inc',
    );

    Кроме того, он также назначает идентификатор партии, который уникален для всех партий.

  2. Теперь пакетные вызовы запрашивают элементы очереди один за другим и выполняют функцию, определенную с заданными в ней аргументами.

  3. Это важная часть. Функция (Операция), которая реализует пакетную операцию, должна разбивать данные на части и обрабатывать их очень эффективно, учитывая ограничение памяти PHP, Time out . Несоблюдение этого требования приведет к вашей проблеме.

Я столкнулся с проблемой тайм-аута, используя миграцию на днях, и начал задаваться вопросом, как пакетный API работает внутри.

Пакетная функция

Функции, которые реализуют Пакет, должны очень внимательно относиться к следующим вещам,

  • Количество элементов в операциях для обработки, как,

    if (!isset($context['sandbox']['progress'])) {
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['current_node'] = 0;
    $context['sandbox']['max'] = db_result(db_query('SELECT COUNT(DISTINCT nid) FROM {node}'));
    }
  • Ограничение количества элементов для обработки в одном вызове функции, например установка предела,

    // For this example, we decide that we can safely process 5 nodes at a time without a timeout.
    $limit = 5;
  • Обновление процесса до пост-обработки, как,

    // Update our progress information.
        $context['sandbox']['progress']++;
        $context['sandbox']['current_node'] = $node->nid;
        $context['message'] = t('Now processing %node', array('%node' => $node->title));
  • Информирование Batch Engine о том, завершена ли партия или нет,

    // Inform the batch engine that we are not finished,
    // and provide an estimation of the completion level we reached.
    if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
      $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
     }

Большинство из вышеперечисленных пунктов позаботятся о пакетных операциях ядра Drupal, если они пропущены в функции реализации. Но всегда лучше определить в функции реализации

Пакетный Законченный обратный звонок

  • Это последний обратный вызов, который вызывается при определении в пакетном массиве. Обычно это отчет о том, сколько обработано и т. Д ...

ОТВЕТЫ

Если страница с пакетным запросом закрыта, останавливается ли пакетная обработка? Будет ли он перезапущен, когда тот же URL открывается снова? Модуль переноса иногда продолжается, но, вероятно, он использует очереди?

Да, в идеале он должен перезапустить пакет и, как сказано выше, он основан на функции, которую вы реализуете.

Чтобы решить вашу проблему с тайм-аутом PHP, используйте пакет Drush, который доступен в модуле переноса, но сначала откопайте пакетные функции переноса и попробуйте разделить данные обработки на части.


1
Потрясающая прогулка. Я также хотел бы отметить, что пакет начинает обработку во время, по крайней мере, для пользователя, «инициализации». экран. То есть, если для настройки первого элемента пакета требуется 4 секунды, а для обработки первого элемента партии - 10 секунд, пользователь увидит процесс «Инициализация». в течение четырнадцати секунд в этом примере. Это имеет смысл, потому что первое сообщение на экране, не являющееся инициализацией, - это «n выполнено», которое будет работать только после обработки некоторых из них. Если это не так, пожалуйста, поправьте меня!
Техас-бронюс

Также из моего опыта. Если вы покинете страницу, то выполняемая пакетная операция / блок будет по-прежнему потреблять ресурсы до тех пор, пока она не будет завершена. Он больше не запускает пакетную работу, но завершает текущую.
Элайджа Линн

10

Если страница с пакетным запросом закрыта, останавливается ли пакетная обработка?

Да, это будет остановлено.

Будет ли он перезапущен, когда тот же URL открывается снова? Модуль переноса иногда продолжается, но, вероятно, он использует очереди?

Как сказал Динеш, все зависит от реализации.

Вы должны запустить миграцию, используя drush, потому что

Drush запускается из командной строки и не подчиняется никаким временным ограничениям (в частности, PHP max_execution_time не применяется). Итак, когда вы запускаете процесс миграции, запущенный с помощью drush, он просто запускается и продолжает работать, пока не будет завершен.

При запуске процессов через веб-интерфейс применяется PHP max_execution_time (обычно 30 секунд, если не меньше). Таким образом, для длительных процессов нам нужно использовать Batch API, который управляет разбиением процесса по нескольким запросам. Итак, процесс миграции запустится, запустится примерно на 25 секунд, затем остановится и позволит пакетному API выдать новый запрос страницы, в котором процесс миграции будет перезапущен до бесконечности.

Итак, понимая это, почему Drush лучше?

Это быстрее

Пакетный API вводит много накладных расходов - закрытие и повторный вызов запросов страниц, процесс миграции должен снова пройти через все необходимые конструкторы, восстановить соединения с базой данных, выполнить запросы повторно и т. Д. И для частичного импорта необходимо выбрать там, где он остановился - если первые 500 исходных записей были импортированы, необходимо найти 501-ю запись. В зависимости от исходного формата и того, как он создан, это может изменяться или не масштабироваться - если вы используете верхние метки с источником SQL, сам запрос может удалить более ранние записи и начать с того места, где вы остановились. Если нет, то Migrate необходимо прокрутить исходные данные в поисках первой не импортированной записи. С, скажем, большой XML-файл в качестве источника,

Это надежнее

Запуск миграций через ваш браузер добавляет ваш рабочий стол и локальное подключение к Интернету в качестве точек сбоя. Сетевой сбой при переходе Batch API на следующий запрос страницы, сбой браузера, случайное закрытие неправильной вкладки или окна могут прервать вашу миграцию. Работа в режиме drush уменьшает количество движущихся частей - вы исключаете свой рабочий стол и локальное подключение к Интернету как факторы.

Это более полезно

Если что-то пойдет не так при работе в Drush, если появятся какие-либо полезные сообщения об ошибках, вы их увидите. Сбои с использованием Batch API часто поглощаются, и все, что вы видите, это абсолютно бесполезный «HTTP-запрос AJAX ненормально завершен. Информация об отладке следующая. Путь: / batch? Id = 901 & op = do StatusText: ResponseText: ReadyState: 4".

Вы можете найти больше информации об этом здесь .

В то же время, если вы хотите запустить пакет, даже если окно браузера закрыто, рассмотрите модуль фонового процесса . У него есть подмодуль Background Batch, который делает свое дело.

Этот модуль берет на себя существующий пакетный API и запускает пакетные задания в фоновом режиме. Это означает, что если вы покинете страницу пакета, задания продолжатся, и вы сможете вернуться к индикатору прогресса позже.


вау, использование drush для миграции сделало огромное улучшение. Я должен перейти на живой сайт, и это значительно снижает нагрузку на систему! Спасибо!
Uwe

0

Тщательно разберитесь в Batch API, и эти модули помогут вам:

1- Progerss Это попытка реализовать общую структуру для отслеживания любого прогресса

2- Фоновый процесс берет на себя существующий пакетный API и запускает пакетные задания в фоновом процессе.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.