循环多卷曲请求PHP的最佳方法

时间:2015-08-17 09:34:35

标签: php multithreading curl

大家好我正在制作一个工具,它将从数据库中获取电话号码并发出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条记录时,这是非常慢的,因为它可以发送下一个卷曲请求,它必须等待响应前一个对吗?问题是如何使每个循环计数20个请求?因为API我每秒使用支持20请求所以我不想最大化它。

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

3 个答案:

答案 0 :(得分:0)

如果您使用的API可以为每个呼叫处理多个号码,那么您可以批量请求移动电话号码的详细信息,而不是逐个发送。 批量请求详细信息将降低请求/响应周期中的成本。

答案 1 :(得分:0)

对于像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 = [];
    }
}

您可以阅读documentation了解更多详情。

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

答案 2 :(得分:0)

$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();
    }
}