我试图为我的战场1战队建立一个网站,在其中一个网页上我想展示我们的团队和他们的一些统计数据。
This API允许我请求我需要的东西,我决定使用php curl请求在我的网站上获取这些数据。这一切都很好,但它超级慢,有时它甚至达到PHP的30s最大值。
这是我的代码
<?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']);
}
?>
我不知道它为什么这么慢,是因为我在localhost上使用xamp还是因为请求正在循环?
提前致谢
答案 0 :(得分:2)
你的循环没有丝毫优化,我相信如果你优化了循环代码,你的代码可以更快地运行。你可以在每次迭代时创建和删除curl句柄,当你可以在每个播放器上重复使用相同的curl句柄时(这将使用更少的cpu并且更快),你不使用压缩传输(启用压缩可能会使传输更快),最重要的是,你顺序运行api调用,我相信如果你并行执行api请求,它会加载更快。另外,你没有urlencode psnid,这可能是一个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 );
另外,如果mysqli_fetch_assoc()导致你的数据库慢速往返,用mysqli_fetch_all()替换它可能会更快
另外,可能比这更快的事情是,每分钟(或每10秒?)运行一次cronjob来缓存结果,并向客户端显示缓存结果。 (即使api调用滞后,客户端页面加载也不会受到影响。)