非常长的加载时间php curl

非常长的加载时间php curl,php,curl,Php,Curl,我正试图为我的战场1氏族建立一个网站,在其中一个页面上,我想显示我们的团队和他们的一些统计数据 API允许我请求所需的数据,我决定使用php curl请求在我的站点上获取这些数据。这一切都非常好,但速度非常慢,有时甚至达到了php的最大值30秒 这是我的密码 <?php $data = $connection->query("SELECT * FROM bfplayers"); while($row = mysqli_fetch_assoc($data)){ $p

我正试图为我的战场1氏族建立一个网站,在其中一个页面上,我想显示我们的团队和他们的一些统计数据

API允许我请求所需的数据,我决定使用php curl请求在我的站点上获取这些数据。这一切都非常好,但速度非常慢,有时甚至达到了php的最大值30秒

这是我的密码

<?php
$data = $connection->query("SELECT * FROM bfplayers");
while($row = mysqli_fetch_assoc($data)){
$psnid = $row['psnid'];


$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "https://battlefieldtracker.com/bf1/api/Stats/BasicStats?platform=2&displayName=".$psnid);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

$headers = [
    'TRN-Api-Key: MYKEY',
];

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);

print($result['profile']['displayName']);
    }
?>

我不知道为什么速度会这么慢,是因为我在本地主机上使用xamp,还是因为请求通过循环


提前感谢

您的循环没有得到任何优化,我相信如果您优化了循环代码,您的代码可以运行得更快。您可以在每次迭代中创建和删除curl句柄,而您可以在每个播放器上重复使用相同的curl句柄(这将使用更少的cpu并更快),您不使用压缩传输(启用压缩可能会使传输更快),最重要的是,您可以按顺序运行api调用,我相信如果您并行处理api请求,它的加载速度会快得多。另外,您没有对psnid进行URL编码,这可能是一个bug。试试这个

<?php
$cmh = curl_multi_init ();
$curls = array ();
$data = $connection->query ( "SELECT * FROM bfplayers" );

while ( ($row = mysqli_fetch_assoc ( $data )) ) {
    $psnid = $row ['psnid'];
    $tmp = array ();
    $tmp [0] = ($ch = curl_init ());
    $tmp [1] = tmpfile ();
    $curls [] = $tmp;
    curl_setopt_array ( $ch, array (
            CURLOPT_URL => "https://battlefieldtracker.com/bf1/api/Stats/BasicStats?platform=2&displayName=" . urlencode ( $psnid ),
            CURLOPT_ENCODING => '',
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_HTTPHEADER => array (
                    'TRN-Api-Key: MYKEY' 
            ),
            CURLOPT_FILE => $tmp [1] 
    ) );
    curl_multi_add_handle ( $cmh, $ch );
    curl_multi_exec ( $cmh, $active );
}
do {
    do {
        $ret = curl_multi_exec ( $cmh, $active );
    } while ( $ret == CURLM_CALL_MULTI_PERFORM );
    curl_multi_select ( $cmh, 1 );
} while ( $active );
foreach ( $curls as $curr ) {
    fseek ( $curr [1], 0, SEEK_SET ); // https://bugs.php.net/bug.php?id=76268
    $response = stream_get_contents ( $curr [1] );
    $result = json_decode ( $response,true );
    print ($result ['profile'] ['displayName']) ;
}
// the rest is just cleanup, the client shouldn't have to wait for this
// OPTIMIZEME: apache version of fastcgi_finish_request() ?
if (is_callable ( 'fastcgi_finish_request' )) {
    fastcgi_finish_request ();
}
foreach ( $curls as $curr ) {
    curl_multi_remove_handle ( $cmh, $curr [0] );
    curl_close ( $curr [0] );
    fclose ( $curr [1] );
}
curl_multi_close ( $cmh );

您的循环一点也没有优化,我相信如果您优化了循环代码,您的代码可以运行得更快。您可以在每次迭代中创建和删除curl句柄,而您可以在每个播放器上重复使用相同的curl句柄(这将使用更少的cpu并更快),您不使用压缩传输(启用压缩可能会使传输更快),最重要的是,您可以按顺序运行api调用,我相信如果您并行处理api请求,它的加载速度会快得多。另外,您没有对psnid进行URL编码,这可能是一个bug。试试这个

<?php
$cmh = curl_multi_init ();
$curls = array ();
$data = $connection->query ( "SELECT * FROM bfplayers" );

while ( ($row = mysqli_fetch_assoc ( $data )) ) {
    $psnid = $row ['psnid'];
    $tmp = array ();
    $tmp [0] = ($ch = curl_init ());
    $tmp [1] = tmpfile ();
    $curls [] = $tmp;
    curl_setopt_array ( $ch, array (
            CURLOPT_URL => "https://battlefieldtracker.com/bf1/api/Stats/BasicStats?platform=2&displayName=" . urlencode ( $psnid ),
            CURLOPT_ENCODING => '',
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_HTTPHEADER => array (
                    'TRN-Api-Key: MYKEY' 
            ),
            CURLOPT_FILE => $tmp [1] 
    ) );
    curl_multi_add_handle ( $cmh, $ch );
    curl_multi_exec ( $cmh, $active );
}
do {
    do {
        $ret = curl_multi_exec ( $cmh, $active );
    } while ( $ret == CURLM_CALL_MULTI_PERFORM );
    curl_multi_select ( $cmh, 1 );
} while ( $active );
foreach ( $curls as $curr ) {
    fseek ( $curr [1], 0, SEEK_SET ); // https://bugs.php.net/bug.php?id=76268
    $response = stream_get_contents ( $curr [1] );
    $result = json_decode ( $response,true );
    print ($result ['profile'] ['displayName']) ;
}
// the rest is just cleanup, the client shouldn't have to wait for this
// OPTIMIZEME: apache version of fastcgi_finish_request() ?
if (is_callable ( 'fastcgi_finish_request' )) {
    fastcgi_finish_request ();
}
foreach ( $curls as $curr ) {
    curl_multi_remove_handle ( $cmh, $curr [0] );
    curl_close ( $curr [0] );
    fclose ( $curr [1] );
}
curl_multi_close ( $cmh );


API是否允许您同时查询多个玩家?这样,您只需提出一个请求,就可以显著减少时间。您正在为表中的每一行提出一个curl请求。我不知道有多少,但很明显,这很快就会失去控制。特别是因为每次通过循环时都会创建和销毁curl处理程序。如果您有30行,那么很明显,远程站点只需要1秒的不太合理的响应时间就可以达到30秒。问题可能来自于在很短的时间内执行curl-inside-while循环的多个请求。这不是最好的方法,但你可以在打印前设置睡眠(0.5),然后再试一次。我想没有人提到过缓存。。因此,如果你经常点击API,并且不需要新的数据,那么本地缓存atm数据库中有15个播放器,所以这并不太多,而且我认为不可能一次从多个播放器请求数据。API允许你一次查询多个播放器吗?这样,您只需提出一个请求,就可以显著减少时间。您正在为表中的每一行提出一个curl请求。我不知道有多少,但很明显,这很快就会失去控制。特别是因为每次通过循环时都会创建和销毁curl处理程序。如果您有30行,那么很明显,远程站点只需要1秒的不太合理的响应时间就可以达到30秒。问题可能来自于在很短的时间内执行curl-inside-while循环的多个请求。这不是最好的方法,但你可以在打印前设置睡眠(0.5),然后再试一次。我想没有人提到过缓存。。因此,如果您经常访问API,并且不需要新数据,本地缓存数据库atm中有15个播放器,因此这并不太多,而且我认为不可能一次从多个播放器请求数据。非常感谢,起初您的代码给了我这个错误:无法使用stdClass类型的对象作为数组。但我通过将json_decode的第二个参数设置为true@CheapGamer有点好奇,它快了多少?你是否对旧代码和新代码进行计时?我的浏览器现在在不到2秒钟的时间内加载页面,这是一个很大的改进say@CheapGamer之前呢?大约17秒,如果加载了的话,非常感谢,一开始你的代码给了我这个错误:不能使用stdClass类型的对象作为数组。但我通过将json_decode的第二个参数设置为true@CheapGamer有点好奇,它快了多少?你是否对旧代码和新代码进行计时?我的浏览器现在在不到2秒钟的时间内加载页面,这是一个很大的改进say@CheapGamer之前呢?大概17秒吧,如果它真的加载了的话