简体   繁体   English

如何将php cronjob分成几部分

[英]How to split php cronjob into parts

There is a PHP script. 有一个PHP脚本。 It gets data from external API and import(update/delete) data into WordPress database (products for Woocommerce). 它从外部API获取数据并导入(更新/删除)数据到WordPress数据库(Woocommerce的产品)。 There are a lot of products... To import all of them the script needs about 2-3 hours. 有很多产品......要导入所有这些产品,脚本需要大约2-3个小时。

The problem is that when the script executes, the memory is not cleaned which leads to its overflow. 问题是当脚本执行时,内存不会被清除,导致溢出。 After that, the script just silently dies without any error. 之后,脚本只是默默地死掉而没有任何错误。

In short, the script looks like this: 简而言之,脚本如下所示:

$products = getProductsFromApi();
foreach ($products as $key => $product) {
    $this->import($product);
}

The idea is to split the cronjob script into parts: if $currentMemory > 100Mb then stop the script and run it again but not from the beginning, from the moment it stopped. 我们的想法是将cronjob脚本分成几部分:如果$currentMemory > 100Mb则停止脚本并再次运行它,但不是从一开始就停止它。

How can this be realized? 怎么能实现呢? If there is a restriction on a server: only 1 cronjob script per 2 hours. 如果服务器有限制:每2小时只有1个cronjob脚本。

Any other ideas? 还有其他想法吗?

You can use a tool such as Gearman to create a queue and workers for importing processes. 您可以使用Gearman之类的工具创建队列和工作人员以导入进程。 You can program each worker to process a certain amount of products that would take time less than the server's maximum execution time. 您可以对每个工作程序进行编程,以处理需要时间少于服务器最长执行时间的一定数量的产品。

Gearman will also allow you to control how many workers can run simultaneously. Gearman还允许您控制可以同时运行的工人数量。 Therefore, the importing process would be faster and you'll make sure the server resources aren't being totally consumed by workers. 因此,导入过程会更快,您将确保服务器资源不被工作人员完全消耗。

You can serilize the $products array when $currentMemory > 100Mb to a file and then execute the script again: 当$ currentMemory> 100Mb到文件时,您可以将$ products数组进行serilize,然后再次执行脚本:

$limit = 100*1000*1000;
$store  = 'products.bin';
$products = [];

if ( !file_exists($store)) {
    $products = getProductsFromApi();    
} else {
    $products = unserialize(file_get_contents($store));
}

foreach ($products as $key => $product) {
    $this->import($product);
    unset($products[$key]);
    if (memory_get_usage() > $limit) {
        file_put_contents($store,serialize($products));
        exec('nohup /usr/bin/php -f myscript.php');
        exit(1);
    }    
}
unlink ($store);

You can use sleep function 你可以使用睡眠功能

For example 例如

  $products = getProductsFromApi();
    $i=0;
    foreach ($products as $key => $product) {
    // you can use your condition here instead of this 
    if($i%10==0){// run ten times then sleep for 100 second    
sleep(100);
    }
        $this->import($product);
    $i++;
    }

https://php.net/manual/en/function.sleep.php https://php.net/manual/en/function.sleep.php

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM