【问题标题】:PHP script for cron job timing out用于 cron 作业超时的 PHP 脚本
【发布时间】:2015-03-07 08:35:29
【问题描述】:

所以我写脚本已经有一段时间了,我写的少数脚本似乎可以正常运行并且没有超时。然而这是一个,我想知道你们是否有关于优化这个脚本速度的建议。

它的工作是从现有数据库中获取 id 并在 API 查找中使用它们来提取项目数据。问题是我必须查找 45000 个项目,并且我已经通过 curl 使用多句柄来处理流程。

我有点卡住了,想知道你们是否有一些想法可以让这个脚本运行得更快以避免超时。

注意:我的数据库连接信息是隐藏的,但我可以正常连接

<?php
$s = microtime(true); //Time request variable

//CONNECT TO THE DATABASE
$DB_NAME = 'database';
$DB_HOST = 'mysql.myhost.com';
$DB_USER = 'myusername';
$DB_PASS = 'mypass';

$con = new mysqli($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME);

if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}
//END OF DB CONNECT

//TP UTIL
function array_2d_to_1d($input_array) {
    $output_array = array();

    for ($i = 0; $i < count($input_array); $i++) {
      for ($j = 0; $j < count($input_array[$i]); $j++) {
        $output_array[] = $input_array[$i][$j];
      }
    }
    return $output_array;
}

function tableExists($con, $table) {
    $show = "SHOW TABLES LIKE '$table'";
    $result = $con->query($show) or die($con->error.__LINE__);
    if($result->num_rows == 1) return true;
    else return false;
}
//END TP UTIL

//++++++++++GET ITEM IDS++++++++++++//
$table = "shinies_primitiveitems_table_NEW";

if(tableExists($con, $table)){
    $query = "SELECT * FROM $table";
    $result = $con->query($query) or die($con->error.__LINE__);
    $index = 0;

    if($result->num_rows > 0) {
        while($row = $result->fetch_assoc()) {
            $urls[$index] = "https://api.guildwars2.com/v2/items/".stripslashes($row['ItemID']);
            //echo $urls[$i]."<br />";
            $index++;
        } //end while loop
    } //end if
}
//++++++++++END GET ITEM IDS++++++++++++//


//++++++++++MULTI CURL REQUESTS FOR API+++++++++++//
// Define the URLs
//$urls = $apiURLArray;

// Create get requests for each URL
$mh = curl_multi_init();
foreach($urls as $i => $url)
{
    //echo $url."<br />";
    $ch[$i] = curl_init($url);
    curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, 1);
    curl_multi_add_handle($mh, $ch[$i]);
}

// Start performing the request
do {
    $execReturnValue = curl_multi_exec($mh, $runningHandles);
} while ($execReturnValue == CURLM_CALL_MULTI_PERFORM);
// Loop and continue processing the request
while ($runningHandles && $execReturnValue == CURLM_OK) {
  // Wait forever for network
  $numberReady = curl_multi_select($mh);
  if ($numberReady != -1) {
    // Pull in any new data, or at least handle timeouts
    do {
      $execReturnValue = curl_multi_exec($mh, $runningHandles);
    } while ($execReturnValue == CURLM_CALL_MULTI_PERFORM);
  }
}

// Check for any errors
if ($execReturnValue != CURLM_OK) {
  trigger_error("Curl multi read error $execReturnValue\n", E_USER_WARNING);
}

// Extract the content
foreach($urls as $i => $url)
{
  // Check for errors
  $curlError = curl_error($ch[$i]);
  if($curlError == "") {
    $res[$i] = curl_multi_getcontent($ch[$i]);
  } else {
    print "Curl error on handle $i: $curlError\n";
  }
  // Remove and close the handle
  curl_multi_remove_handle($mh, $ch[$i]);
  curl_close($ch[$i]);
}
// Clean up the curl_multi handle
curl_multi_close($mh);

//var_dump(json_decode($res, true));
//echo count($res)."<br />";

//Decode data
for($i=0;$i<count($res);$i++){
    $dataArray[$i] = json_decode($res[$i], true);
    //echo "$i: ".json_decode($res[$i], true)."<br /><br />";
}
//echo count($dataArray)."<br />";
//var_dump($dataArray);


//$data = array_2d_to_1d($dataArray);

//echo count($data)."<br />";
/*
//Find attributes of each item
for($i=0;$i<count($data);$i++){
    echo $data[$i]['name']." - ".$data[$i]['icon'];
}*/

//turn dataArray into a single dimensional data array
//$data = array_2d_to_1d($dataArray);

//print_r($data);
//++++++++++END REQUEST+++++++++++//


// Print the response data - DEBUG
echo "<p>Total request time: ".round(microtime(true) - $s, 4)." seconds.";
?>

【问题讨论】:

  • 如果你想让别人检查你的代码,你应该在Code Review询问

标签: php curl optimization cron timeout


【解决方案1】:

脚本是否由于最大执行时间限制而超时?如果是这样,也许您可​​以使用http://php.net/manual/en/function.set-time-limit.php 或其他方式将超时设置为更大的值?

如果在所有 curl 项目都停止返回的意义上超时,则可能是远程端对请求有速率限制,或者如果您尝试同时启动 45,000 个 TCP 请求或其他什么,您会遇到其他限制?

【讨论】:

  • 你知道我还没有真正想过,但你可能会有所收获。如果我必须保持在内存限制以下,也许我要求一次获取 45000 个项目的信息并不是最好的做法。我知道它现在不是超时问题,但肯定是内存限制崩溃,因为它不会花费很长时间。
  • 啊,在这种情况下,也许你可以使用类似 ini_set('memory_limit', '512M');如果它只是达到软内存限制(或者如果它达到硬内存限制,则一次将请求分解为 1,000 个子集)。
  • 这篇文章中的脚本使我的服务器崩溃了,所以我认为我达到了硬限制,因为我必须等待主机重新启动我的 VPS
  • 啊。是的,那么肯定将它分批成更小的子集!祝你好运!
猜你喜欢
  • 2012-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多