Maison  >  Article  >  développement back-end  >  L'implémentation simultanée de la fonction curl dans PHP réduit le temps d'accès au backend

L'implémentation simultanée de la fonction curl dans PHP réduit le temps d'accès au backend

零到壹度
零到壹度original
2018-04-10 11:36:091547parcourir

Le contenu de cet article est de partager avec vous l'implémentation de la simultanéité de la fonction curl en PHP pour réduire le temps d'accès au back-end. Elle a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer

Tout d'abord. , comprenons la fonction multithread PHP curl dans :

# curl_multi_add_handle
# curl_multi_close
# curl_multi_exec
# curl_multi_getcontent
# curl_multi_info_read
# curl_multi_init
# curl_multi_remove_handle
# curl_multi_s elect

De manière générale, lorsque l'on pense utiliser ces fonctions, le but doit évidemment être de demander plusieurs URL en même temps, plutôt que de les demander une par une. Sinon, il vaut mieux le faire. bouclez et ajustez curl_exec vous-même.

Les étapes sont résumées comme suit :

Étape 1 : Appeler curl_multi_init
Étape 2 : Appeler curl_multi_add_handle dans une boucle
Il est à noter dans cette étape que le deuxième paramètre de curl_multi_add_handle est donné par Subhandle de curl_init.
Étape 3 : Continuez à appeler curl_multi_exec
Étape 4 : Appelez curl_multi_getcontent en boucle pour obtenir les résultats nécessaires
Étape 5 : Appelez curl_multi_remove_handle et appelez curl_close pour chaque descripteur de mot
Étape 6 : Appelez curl_multi_close

Voici un exemple simple trouvé en ligne. L'auteur le qualifie d'exemple sale (j'expliquerai pourquoi il est sale plus tard) :

/*
Here's a quick and dirty example for curl-multi from PHP, tested on PHP 5.0.0RC1 CLI / FreeBSD 5.2.1
*/
$connomains = array(
"http://www.cnn.com/",
"http://www.canada.com/",
"http://www.yahoo.com/"
);
$mh = curl_multi_init();
foreach ($connomains as $i => $url) {
     $conn[$i]=curl_init($url);
      curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,1);
      curl_multi_add_handle ($mh,$conn[$i]);
}
do { $n=curl_multi_exec($mh,$active); } while ($active);
foreach ($connomains as $i => $url) {
      $res[$i]=curl_multi_getcontent($conn[$i]);
      curl_close($conn[$i]);
}
print_r($res);

L'ensemble du processus d'utilisation est. presque la même chose. Cependant, ce code simple a une faiblesse fatale, c'est-à-dire que la partie de la boucle do est une boucle infinie pendant toute la requête URL, ce qui peut facilement faire occuper le CPU à 100 %.

Améliorons-le maintenant. Ici, nous devons utiliser une fonction curl_multi_select qui n'a presque aucune documentation. Bien que la bibliothèque curl de C ait des instructions pour la sélection, l'interface et l'utilisation en PHP sont en effet différentes de celles en C. .

Modifiez la section "faire" ci-dessus comme suit :
                                                                                                                                              La valeur de retour détermine s'il y a encore des données. Lorsqu'il y a des données, curl_multi_exec est appelé en continu. S'il n'y a pas de données pour le moment, il entre. la phase de sélection Une fois que de nouvelles données arrivent, elles peuvent être réveillées pour continuer l'exécution. L’avantage ici est qu’il n’y a pas de consommation inutile de CPU.

 do {
                        $mrc = curl_multi_exec($mh,$active);
                } while ($mrc == CURLM_CALL_MULTI_PERFORM);
                while ($active and $mrc == CURLM_OK) {
                        if (curl_multi_select($mh) != -1) {
                                do {
                                        $mrc = curl_multi_exec($mh, $active);
                                } while ($mrc == CURLM_CALL_MULTI_PERFORM);
                        }
                }
De plus : Il y a quelques détails que vous pouvez rencontrer parfois :


Contrôlez le délai d'attente de chaque requête, faites-le via curl_setopt avant curl_multi_add_handle :
curl_setopt($ch , CURLOPT_TIMEOUT, $ timeout);

Pour déterminer s'il y a un délai d'attente ou d'autres erreurs, utilisez : curl_error($conn[$i]);



Ici J'utilise simplement le sale exemple mentionné ci-dessus (c'est suffisant, et je n'ai pas trouvé d'utilisation du processeur à 100%).

Simuler la concurrence sur une certaine interface de "Kandian.com". La fonction est de lire et d'écrire des données dans memcache. Pour des raisons de confidentialité, les données et résultats pertinents ne seront pas publiés.

Simulé trois fois. La première fois, 10 threads demandés 1000 fois en même temps. La deuxième fois, 100 threads demandés 1000 fois en même temps. temps (c'est déjà assez pénible, je n'ose pas dans des décors à plus de 1000 multithreads).

Il semble que la concurrence de simulation multithread curl ait encore certaines limites.

De plus, je soupçonnais également qu'il pouvait y avoir une erreur importante dans les résultats en raison du retard multi-thread, et je l'ai découvert en comparant les données. Il n'y a pas beaucoup de différence dans le temps nécessaire à l'initialisation et à la définition. La différence réside dans la méthode get, cela peut donc être simplement exclu ~~~

Habituellement, cURL en PHP s'exécute de manière bloquante, c'est-à-dire c'est-à-dire qu'après avoir créé une requête cURL, vous devez attendre qu'elle s'exécute correctement ou expire avant d'exécuter la requête suivante. La série de fonctions curl_multi_* permet un accès simultané réussi. La documentation PHP ne présente pas cette fonction en détail. suit :

  1. $requests = array('http://www.baidu.com', 'http://www.google.com');  
    $main    = curl_multi_init();  
    $results = array();  
    $errors  = array();  
    $info = array();  
    $count = count($requests);  
    for($i = 0; $i < $count; $i++)   
    {    
    $handles[$i] = curl_init($requests[$i]);    
    var_dump($requests[$i]);    
    curl_setopt($handles[$i], CURLOPT_URL, $requests[$i]);    
    curl_setopt($handles[$i], CURLOPT_RETURNTRANSFER, 1);    
    curl_multi_add_handle($main, $handles[$i]);  
    }  
    $running = 0;   
    do {    
    curl_multi_exec($main, $running);  
    }   
    while($running > 0);   
    for($i = 0; $i < $count; $i++)  
    {  $results[] = curl_multi_getcontent($handles[$i]);    
    $errors[]  = curl_error($handles[$i]);    
    $info[]    = curl_getinfo($handles[$i]);    
    curl_multi_remove_handle($main, $handles[$i]);  
    }  
    curl_multi_close($main);  
    var_dump($results);  
    var_dump($errors);  
    var_dump($info);

前言:在我们平时的程序中难免出现同时访问几个接口的情况,平时我们用curl进行访问的时候,一般都是单个、顺序访问,假如有3个接口,每个接口耗时500毫秒那么我们三个接口就要花费1500毫秒了,这个问题太头疼了严重影响了页面访问速度,有没有可能并发访问来提高速度呢?今天就简单的说一下,利用curl并发来提高页面访问速度,希望大家多指导。1、老的curl访问方式以及耗时统计

  1. <?php function curl_fetch($url, $timeout=3){       
    $ch = curl_init();       
    curl_setopt($ch, CURLOPT_URL, $url);       
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);       
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);       
    $data = curl_exec($ch);       
    $errno = curl_errno($ch);       
    if ($errno>0) {           
    $data = false;       
    }       
    curl_close($ch);       
    return $data;   
    }   
    function microtime_float()   
    {      
    list($usec, $sec) = explode(" ", microtime());      
    return ((float)$usec + (float)$sec);   
    }   
    $url_arr=array(        
    "taobao"=>"http://www.taobao.com",        
    "sohu"=>"http://www.sohu.com",        
    "sina"=>"http://www.sina.com.cn",        
    );    
    $time_start = microtime_float();    
    $data=array();    
    foreach ($url_arr as $key=>$val)    
    {        
    $data[$key]=curl_fetch($val);    
    }    
    $time_end = microtime_float();    
    $time = $time_end - $time_start;    
    echo "耗时:{$time}";   
    ?>

耗时:0.614秒 
2、curl并发访问方式以及耗时统计

  1. <?php   
    function curl_multi_fetch($urlarr=array()){       
    $result=$res=$ch=array();       
    $nch = 0;       
    $mh = curl_multi_init();       
    foreach ($urlarr as $nk => $url) {           
    $timeout=2;           
    $ch[$nch] = curl_init();           
    curl_setopt_array($ch[$nch], array(           
    CURLOPT_URL => $url,           
    CURLOPT_HEADER => false,           
    CURLOPT_RETURNTRANSFER => true,           
    CURLOPT_TIMEOUT => $timeout,           
    ));           
    curl_multi_add_handle($mh, $ch[$nch]);           
    ++$nch;     }       
    /* wait for performing request */      
    do {           
    $mrc = curl_multi_exec($mh, $running);       
    } while (CURLM_CALL_MULTI_PERFORM == $mrc);         
    while ($running && $mrc == CURLM_OK) {           
    // wait for network           
    if (curl_multi_select($mh, 0.5) > -1) {               
    // pull in new data;               
    do {                   
    $mrc = curl_multi_exec($mh, $running);               
    } while (CURLM_CALL_MULTI_PERFORM == $mrc);           
    }       
    }         
    if ($mrc != CURLM_OK) {           
    error_log("CURL Data Error");       
    }         
    /* get data */      
    $nch = 0;       
    foreach ($urlarr as $moudle=>$node) {           
    if (($err = curl_error($ch[$nch])) == &#39;&#39;) {               
    $res[$nch]=curl_multi_getcontent($ch[$nch]);             $result[$moudle]=$res[$nch];         }           
    else          
    {               
    error_log("curl error");           
    }           
    curl_multi_remove_handle($mh,$ch[$nch]);           
    curl_close($ch[$nch]);           
    ++$nch;       
    }       
    curl_multi_close($mh);       
    return  $result;   
    }   
    $url_arr=array(        
    "taobao"=>"http://www.taobao.com",        
    "sohu"=>"http://www.sohu.com",        
    "sina"=>"http://www.sina.com.cn",        
    );   
    function microtime_float()   
    {      
    list($usec, $sec) = explode(" ", microtime());      
    return ((float)$usec + (float)$sec);   
    }   
    $time_start = microtime_float();   
    $data=curl_multi_fetch($url_arr);   
    $time_end = microtime_float();   
    $time = $time_end - $time_start;   
    echo "耗时:{$time}";   
    ?>

耗时:0.316秒
帅气吧整个页面访问后端接口的时间节省了一半

3、curl相关参数
curl_close — Close a cURL session
curl_copy_handle — Copy a cURL handle along with all of its preferences
curl_errno — Return the last error number
curl_error — Return a string containing the last error for the current session
curl_exec — Perform a cURL session
curl_getinfo — Get information regarding a specific transfer
curl_init — Initialize a cURL session
curl_multi_add_handle — Add a normal cURL handle to a cURL multi handle
curl_multi_close — Close a set of cURL handles
curl_multi_exec — Run the sub-connections of the current cURL handle
curl_multi_getcontent — Return the content of a cURL handle if CURLOPT_RETURNTRANSFER is set
curl_multi_info_read — Get information about the current transfers
curl_multi_init — Returns a new cURL multi handle
curl_multi_remove_handle — Remove a multi handle from a set of cURL handles
curl_multi_select — Wait for activity on any curl_multi connection
curl_setopt_array — Set multiple options for a cURL transfer
curl_setopt — Set an option for a cURL transfer
curl_version — Gets cURL version information

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn