循环多旋请求PHP的最佳方法


Best approach for Looped Multi-Curl Request PHP

我正在制作一个工具,它将从数据库中获取电话号码,并使curl/api请求验证该号码并获取其信息,然后根据api响应更新数据库中的某些字段。

我有一个名为phones的表,里面有

->id
->number
->network
->country

所以在我的表中只有idnumber有值,networkcountry是空的。这就是我将使用API根据数字更新那些字段的原因。但是这里有一个问题我将循环所有这些数字,像这样:

$phone = Phone::all();
foreach ($phone as $key => $value) 
{
  // Call the API that will get the details in the current number
  // and update the details in the table for the current number 
  /** Some code for API Call **/
  //Update Script
  $update = Phone::find($value->id);
  $update->network = $network;
  $update->country = $country;
  $update->country_prefix = $country_prefix;
  $update->status = $status;
  $update->remarks = $remarks;
  $update->save();
}

这可以很好地完成我的任务,但问题是,当我循环输入50,000条记录时,速度很慢,因为在它发送下一个curl请求之前,它必须等待前一个请求的响应?问题是我如何使它每循环计数为20个请求?因为我使用的API支持每秒20个请求,所以我不想最大化它。

我知道我的循环将改变,因为我需要一次获得20条记录,而不是再次重复相同的记录

对于像GuzzleHttp这样的库来说,这是相当容易的。我不知道你的对象结构或验证例程是什么样子,但是这个例子应该让你开始:

use GuzzleHttp'Client;
use GuzzleHttp'Promise;
$client = new Client(['base_uri' => 'http://example.com/api/']);
$updates = [];
$phone = Phone::all();
foreach ($phone as $key => $value)
{
    $update = Phone::find($value->id);
    $update->network = $network;
    $update->country = $country;
    $update->country_prefix = $country_prefix;
    $update->status = $status;
    $update->remarks = $remarks;
    // Load updates into array for processing
    $updates[$update->id] = $update;
    if (count($updates) == 20) {
        // Setting up the async requests
        $promises = [];
        foreach ($updates as $u) {
            // This is posting to http://example.com/api/phone, appending to the 'base_uri' above.
            // This will send a json body, but you can change the format as necessary
            $promises[$u->id] = $client->postAsync('/phone', ['json' => ['phone' => $u->number]]);
        }
        // Waits for the requests to complete
        $results = Promise'unwrap($promises);
        // Saves each number with a 200 response
        foreach ($results as $id => $result) {
            if ($result->getStatusCode() == 200) {
                $updates[$id]->save();
            }
        }
        // Clear processed records from array
        $updates = [];
    }
}

您可以通读文档了解更多细节。

您也可以对curl_multi_*执行此操作,但实现要复杂得多。

如果您正在使用的API每次呼叫可以处理多个号码,那么您可以批量请求手机号码的详细信息,而不是逐个发送。批量请求详细信息将减少请求/响应周期中的成本。

$phone = Phone::all();
$counter=0;
$some_threshold=100; 
$requestArray = array();
foreach ($phone as $key => $value) 
{
    $requestArray[] = $value;
    if($counter >= $some_threshold)
    {
          // Call the API that will get the details in the  numbers in $requestArray 
          foreach($response as $result)
          {
              $update = Phone::find($value->id);
              $update->network = $network;
              $update->country = $country;
              $update->country_prefix = $country_prefix;
              $update->status = $status;
              $update->remarks = $remarks;
              $update->save();
          }
         $counter=0;
         $requestArray = array();
    }
}