简体   繁体   English

我们如何异步同时发出多个 php http 请求?

[英]How can we make multiple php http request at the same time asynchronously?

I'm currently working on a project with my friends, so let me explain:我目前正在和我的朋友一起做一个项目,所以让我解释一下:

We have a mySql database filled with english postcode from London, one table with universities, and one with hosts, what we want is to actually calculate the public transport travel time between all the host and the universities and save it into another table of the database that will have the host postcode, the university post code and the travel time between the both on one line, and etc...我们有一个 mySql 数据库,里面有来自伦敦的英文邮政编码,一张表是大学,一张是主机,我们想要实际计算所有主机和大学之间的公共交通旅行时间,并将其保存到数据库的另一张表中这将有主机邮政编码,大学邮政编码和两者之间的旅行时间在一条线上,等等......

For that we are doing http request to the tfl API that return to us a JSON with all the travel details (and of course the travel time), that we then decode and keep only what we want (travel time).为此,我们正在向 tfl API 发出 http 请求,该请求返回给我们一个带有所有旅行详细信息(当然还有旅行时间)的 JSON,然后我们对其进行解码并只保留我们想要的内容(旅行时间)。

The problem is that we have a quite big database with almost 250 host and 800 universities that give us around 200 000 request and a too long process time to be used (with the api response time and the php treatment, around 19h)问题是我们有一个相当大的数据库,有近 250 个主机和 800 所大学,给我们大约 200 000 个请求和一个太长的处理时间(API 响应时间和 php 处理,大约 19 小时)

We tried to see if we could use the cURL method to split the process between multiple loop so that we can divide the process time by the number of cURL we made but we can't manage to figure how we can do that...我们试图看看是否可以使用 cURL 方法在多个循环之间拆分进程,以便我们可以将进程时间除以我们制作的 cURL 数量,但我们无法弄清楚如何做到这一点......

The final goal is to make a small local app that when we select one university it give us the nearests 10 hosts in public transport.最终目标是制作一个小型本地应用程序,当我们选择一所大学时,它会为我们提供最近的 10 个公共交通主机。

Does anyone have any experience with that kind of things and can help us ?有没有人有这种事情的经验并且可以帮助我们?

Here is what we have right now :这是我们现在拥有的:

//postCodeUni list contains all the universites objects
foreach ($postCodeUni as $uniPostCode) {

    //here we take the postcode from the university object
    $uni = $uniPostCode['Postcode'];

    //postCodeHost list contains all the host objects
    foreach ($postCodeHost as $hostPostCode) {

        //here we take the postcode from the host object
        $host = $hostPostCode['Postcode'];

        //here we make an http request to the tfl api that return us a journey between the two post codes (a json with all the journey details)
        $data =  json_decode(file_get_contents('https://api.tfl.gov.uk/journey/journeyresults/' . $uni . '/to/' . $host . '?app_key=a59c7dbb0d51419d8d3f9dfbf09bd5cc'), true);

        //here we save the multiple duration times (because there is different ways to travel between two point with public transport)
        $duration = $data['journeys'];

        $tableTemp = [];

        foreach ($duration as $durations) {
            $durationns = $durations['duration'];
            array_push($tableTemp, $durationns);
        }

        //We then take the shorter one
        $min = min($tableTemp);

        echo "Shorter travel time : " . $min . " of travel between " . $uni . " and ". $host . " . <br>";

        echo "<br>";

        //We then save this time in a table that will contain the travel time of all the journeys to do comparaison
        array_push($tableAllRequest, array($uni . " and ". $host => $min));
    }
}

There are many ways to achieve this however the easiest imo would be to use Guzzle Async (cURL multi interface under the hood).有很多方法可以实现这一点,但最简单的 imo 是使用 Guzzle Async(引擎盖下的 cURL 多接口)。 Take a look at this answer - Guzzle async requests not really async?看看这个答案 - Guzzle async requests not really async? example below,下面的例子,

<?php
use GuzzleHttp\Promise;
use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'http://httpbin.org/']);

// Initiate each request but do not block
$promises = [
    'image' => $client->getAsync('/image'),
    'png'   => $client->getAsync('/image/png'),
    'jpeg'  => $client->getAsync('/image/jpeg'),
    'webp'  => $client->getAsync('/image/webp')
];

// Wait on all of the requests to complete. Throws a ConnectException
// if any of the requests fail
$results = Promise\unwrap($promises);

// Wait for the requests to complete, even if some of them fail
$results = Promise\settle($promises)->wait();

// Loop through each response in the results and fetch data etc
foreach($results as $promiseKey => $result) {

    // Data response
    $dataOfResponse = ($result['value']->getBody()->getContents());

    // Status
    echo $promiseKey . ':' . $result['value']->getStatusCode() . "\r\n";
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM