【问题标题】:PHP CURL Request in For-Loop really slowFor-Loop中的PHP CURL请求真的很慢
【发布时间】:2020-11-07 23:57:53
【问题描述】:

我正在创建一个公会主页,其中有一个显示我们公会名册的页面。使用 Oauth 从暴雪 API 中提取数据,到目前为止一切正常。问题是花名册页面至少需要 10 秒才能加载。使用 Postman,我通常会在 200 毫秒内得到结果。我进行了测试,发现 for 循环中的请求减慢了很多。因为这是我第一次使用 curl,所以我的代码有点乱。您有任何提示如何改进 for 循环中的请求吗?提前致谢

<?php


$curl_handle = curl_init();

curl_setopt($curl_handle, CURLOPT_URL, "https://eu.battle.net/oauth/token");
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, ['grant_type' => 'client_credentials']);
curl_setopt($curl_handle, CURLOPT_USERPWD, $apikey . ':' . $apisecret);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_setopt($curl_handle, CURLOPT_USERAGENT, 'Mozilla/5.001 (windows; U; NT4.0; en-US; rv:1.0) Gecko/25250101');
curl_setopt($curl_handle, CURLOPT_HTTPHEADER, ['Content-Type: multipart/form-data']);


$response = curl_exec($curl_handle);
$access_token = json_decode($response)->access_token;


curl_reset($curl_handle);

curl_setopt($curl_handle, CURLOPT_URL, "https://eu.api.blizzard.com/data/wow/guild/malfurion/war-hounds/roster?namespace=profile-eu");
curl_setopt($curl_handle, CURLOPT_HTTPHEADER, ['Content-Type: multipart/form-data','Authorization: Bearer ' . $access_token]);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_setopt($curl_handle, CURLOPT_USERAGENT, 'Mozilla/5.001 (windows; U; NT4.0; en-US; rv:1.0) Gecko/25250101');


$guildrequest = curl_exec($curl_handle);
$guildname = json_decode($guildrequest, true);
$name1 = $guildname['members'];

curl_reset($curl_handle);
curl_setopt($curl_handle, CURLOPT_HTTPHEADER, ['Content-Type: multipart/form-data','Authorization: Bearer ' . $access_token]);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_setopt($curl_handle, CURLOPT_USERAGENT, 'Mozilla/5.001 (windows; U; NT4.0; en-US; rv:1.0) Gecko/25250101');


echo "<table style=\"background-color:#595959;border:2px solid black\">";
echo "<tr><th>Roster</th><th>Name</th><th>Klasse</th></tr>";
echo "<style> tr:nth-child(even) {background-color: #4a4a4a;} table{border-collapse: collapse;} 
</style>";

for($i=0; $i<count($name1);$i++)
{
//player-class general json
curl_setopt($curl_handle, CURLOPT_URL, $name1[$i][character][playable_class][key][href]);
$playerClass = curl_exec($curl_handle);
$playerClassName = json_decode($playerClass, true);

//player-class media
curl_setopt($curl_handle, CURLOPT_URL, $playerClassName[media][key][href]);
$icon = curl_exec($curl_handle);
$playerClassIcon = json_decode($icon, true);
$urlPrep = $playerClassIcon[assets][0][value];
$url = str_replace( 'https://', 'http://', $urlPrep);
 
//player general json
curl_setopt($curl_handle, CURLOPT_URL,$name1[$i][character][key][href]);
$character = curl_exec($curl_handle);
$characterJSON = json_decode($character, true);
 
//player media
$urlMedia = $characterJSON[media][href];
curl_setopt($curl_handle, CURLOPT_URL,$urlMedia);
$charactermedia = curl_exec($curl_handle);
$charactermediaJSON = json_decode($charactermedia,true);
$urlPrep2 = $charactermediaJSON[assets][0][value];

if($urlPrep2 == null){

    $urlPrep2 = $charactermediaJSON[avatar_url];
}
$url2 = str_replace( 'https://', 'http://', $urlPrep2);

$color = black;

echo "<tr><td><img src=\"" .$url2. "\" alt=\"".$name1[$i][character][name]. "\"></td><td style=\"font-weight:bold;color:".$color."\"><a style=\"font-weight:bold;color:".$color."\" href=\"https://worldofwarcraft.com/de-de/character/eu/".$name1[$i][character][realm][slug]."/".$name1[$i][character][name]."\">" .$name1[$i][character][name]. "</a></td><td><img src=\"" .$url. "\" alt=\"" .$playerClassName[name][de_DE]. "\" ></td></tr>";

}
?>

【问题讨论】:

    标签: php wordpress loops curl


    【解决方案1】:

    首先,原则上,我建议您隐藏您的 API 密钥,假设您已经展示了真实的密钥。

    至于您的问题,无需查看您的其余代码并尝试使其更高效 - 或者研究其他 API 请求模式是否也可以正常工作或更好的问题 - 我建议您考虑保存返回的值作为可重复使用的瞬变,而这些瞬变仅在必要时才会被刷新。后一个目标可以通过多种不同的方式来处理,但主要结果是不需要每次重新加载页面输出时都需要发出一组请求。

    https://developer.wordpress.org/apis/handbook/transients/

    【讨论】:

      【解决方案2】:

      永远不要这样做

      curl_setopt($curl_handle, CURLOPT_POSTFIELDS, [
          'grant_type' => 'client_credentials'
      ]);
      curl_setopt($curl_handle, CURLOPT_HTTPHEADER, [
          'Content-Type: multipart/form-data'
      ]);
      

      您可能会破坏请求,请求应该如下所示:

      Content-Length: 163
      Content-Type: multipart/form-data; boundary=------------------------becb5cf73f034d20
      
      --------------------------becb5cf73f034d20
      Content-Disposition: form-data; name="grant_type"
      
      client_credentials
      --------------------------becb5cf73f034d20--
      
      

      当您尝试覆盖 curl 自动生成的 multipart-header 时,您可能会从 header 中删除边界,使请求无法解析,因此让 curl 自动生成 multipart 标头,不要覆盖它。

      优化.. 获取 oAuth 令牌的第一个请求可以替换为每分钟 24/7 的每分钟 cronjob 生成一个新令牌并将其存储在数据库中。从您自己的数据库中获取令牌应该比从暴雪生成一个新令牌要快得多,这样会加快速度:始终使用 cronjobs 生成新令牌并将其缓存。

      但由于您发送的请求根本不是动态的,它似乎不依赖于任何 $_GET 或 $_POST 请求,或类似的东西,有一个 cronjob 每分钟生成一个新的 html 页面,并且只是为您的最新版本的 html 文件会快得多。 cronjob 可以运行的最快速度是每 60 秒,如果这对您来说太慢(例如,您需要每 10 秒或 30 秒),然后考虑使用守护进程,或者您可以使用一些 cronjob-hacks,例如每分钟有 cronjob php generateHtml.php,你有 sleep 30 &amp;&amp; php generateHtml.php - 这个 hack 将允许你每 30 秒运行一次 cronjob,而不是正常的 1 分钟限制;你可以对sleep 10 &amp;&amp; + sleep 20 &amp;&amp; 等做同样的事情,让 cronjob 甚至每 10 秒运行一次。

      使用 cronjob 将使您的实际页面加载需要几毫秒,而不是您现在所遭受的 10 多秒 :)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-28
        • 2017-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-24
        • 2013-03-24
        相关资源
        最近更新 更多