批处理API如何在内部工作?


19

前几天我遇到了使用迁移的超时问题,开始想知道Batch API在内部如何工作。

我的理解是,您将以最简单的形式传递值数组(例如,nids)和一个对这些值进行运算的函数。然后,批处理API会对每个请求处理固定数量的这些值,直到完成为止。

在运行批处理时,页面似乎使用Ajax请求来显示批处理操作的进度(完成百分比和消息)。我认为它会等到请求完成以更新进度后再立即启动下一个请求?

如果关闭了带有批处理请求的页面,则批处理会停止吗?再次打开相同的URL,它会重新启动吗?迁移模块有时会继续,但是可能正在使用队列?

Answers:


40

这是批处理的工作方式(基于我的理解)

1. 初始化

  1. 初始化批处理。基于客户端(浏览器)配置是否启用JavaScript。
  2. 启用JavaScript的客户端由drupal.js中设置的“ has_js” cookie标识。如果在当前用户的浏览器会话期间未访问启用JavaScript的页面,则返回非JavaScript版本。
  3. 如果启用了JavaScript的 Batch使用ajax请求,则在请求中保持活动连接。
  4. 如果未启用JavaScript,则 Batch使用在html中设置一个meta标记进行定期刷新,以使连接在整个请求中保持活动状态。

(这是进度栏如何更新“完成的工作”进度的方式。)

批处理

  1. 首先,批处理创建一个队列,并添加您在批处理数组中定义的所有操作(函数和参数),例如,

    $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',
    );

    此外,它还分配了一个批次ID,该ID在批次之间是唯一的。

  2. 现在,批处理调用逐个声明队列项,并执行使用其中定义的参数定义的功能。

  3. 这是至关重要的部分,考虑到PHP的内存限制Time out,实现批处理操作的函数(操作)应该对数据进行分块并非常有效地处理数据。不这样做将导致您的问题。

前几天我遇到了使用迁移的超时问题,开始想知道批处理API在内部如何工作。

批处理功能

实现Batch的功能应非常谨慎地注意以下事项,

  • 操作中要处理的项目数,例如

    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));
  • 通知批次引擎批次是否完成,

    // 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的Core批处理操作。但是总是最好在实现函数中定义

批处理完成的回调

  • 这是在批处理数组中定义时最后一次调用的回调方法,通常是有关处理量等的报告。

答案

如果关闭了带有批处理请求的页面,则批处理会停止吗?再次打开相同的网址时,它会重新启动吗?迁移模块有时会继续,但是可能正在使用队列?

是的,理想情况下,它应该重新启动批处理,并且如上所述,它基于您实现的功能。

解决您的PHP超时问题,请使用M迁移模块中提供的Drush批处理,但是首先要挖掘出迁移的批处理功能,然后尝试对您的处理数据进行分块。


1
很棒的演练。我还想指出,该批处理确实在至少对用户来说似乎是“正在初始化”的过程中开始处理。屏幕。也就是说,如果设置过程需要4秒钟,而处理第一个批处理项目则需要10秒钟,那么用户将看到过程“正在初始化”。在此示例中持续14秒。这是有道理的,因为第一个非初始化屏幕消息是“ n complete”,仅在处理某些消息后才起作用。如果这是错误的,请纠正我!
texas-bronius

另外,根据我的经验。如果您离开该页面,则正在进行的批处理操作/块将仍然消耗资源,直到完成为止。它不会触发批处理作业,但会完成当前的作业。
伊利亚·林恩2015年

10

如果关闭了带有批处理请求的页面,则批处理会停止吗?

是的,它将停止。

再次打开相同的网址时,它会重新启动吗?迁移模块有时会继续,但是可能正在使用队列?

正如Dinesh所说,这取决于实现。

您应该使用drush运行迁移,因为

Drush在命令行运行,不受任何时间限制(特别是PHP的max_execution_time不适用)。因此,当您启动通过drush运行的迁移过程时,它只是启动并一直运行直到完成。

通过Web界面运行进程时,适用PHP max_execution_time(通常为30秒,如果不短的话)。因此,对于长时间运行的流程,我们需要使用Batch API,该API管理跨多个请求的流程分解。因此,迁移过程将启动,运行25秒钟左右,然后停止并让Batch API发出新的页面请求,并无限期地重启迁移过程。

因此,了解到为什么Drush更好?

快一点

Batch API会带来很多开销-关闭并重新调用页面请求,迁移过程需要再次通过所有必要的构造函数运行,重新建立数据库连接并重新运行查询等。此外,对于部分导入,还需要选择从上次停止的位置开始-如果已导入前500条源记录,则需要找到第501条记录。取决于您的源格式及其构造方式,这可能会缩放,也可能不会缩放-如果您在SQL源中使用高水位标记,则查询本身可以消除较早的记录,并从您上次中断的地方开始。如果不是,则Migrate需要滚动查看源数据以查找第一个未导入的记录。假设有一个大的XML文件作为您的源,

更可靠

通过浏览器运行迁移会将您的桌面和本地Internet连接添加为故障点。当Batch API移至下一个页面请求时,网络故障,浏览器崩溃,错误的选项卡或窗口意外关闭都可能中断您的迁移。匆忙运行减少了活动部件-消除了桌面和本地Internet连接的因素。

更有帮助

如果在Drush中运行时某些地方出了问题,如果有任何有用的错误消息,您将看到它们。使用Batch API的失败常常被吞没,您所看到的只是完全没用的“ AJAX HTTP请求异常终止。调试信息如下。路径:/ batch?id = 901&op = do StatusText:ResponseText:ReadyState:4”。

您可以在此处找到更多信息。

同时,如果即使关闭浏览器窗口也要运行批处理,请考虑使用“ 后台进程”模块。它有一个完成该功能的子模块Background Batch

该模块将接管现有的Batch API,并在后台进程中运行批处理作业。这意味着,如果您退出批处理页面,则作业将继续,并且您可以稍后返回进度指示器。


哇,使用草编进行迁移有了很大的进步。我必须迁移到一个实时站点,这将给系统带来更少的负载!谢谢!
uwe 2012年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.