2016-02-21 2 views
5

Devo chiamare un numero elevato di API contemporaneamente. Sto cercando di farlo tramite curl multi-thread, ma sembra che non riesca a ottenere tutti i risultati API correttamente (alcuni errori, penso che sia il timeout ???) se gli passassi un sacco di URL . 50 URL alla volta sembra essere il massimo che posso passarlo, e circa 100 alla volta è quando ho davvero iniziato a vedere i problemi. Per questo motivo, ho dovuto implementare la logica per bloccare gli URL che cerco di arricciare in un dato momento.Il ricciolo multi-thread non può gestire un numero elevato di URL simultanei?

Domande:

  1. che cosa potrebbe causare i miei problemi di arricciatura?
  2. C'è qualcosa in ricciolo che posso impostare per dire che aspetti più a lungo le risposte - nel caso in cui i miei problemi abbiano qualcosa a che fare con i timeout?
  3. C'è qualcosa nel mio server/php.ini che posso configurare per migliorare le prestazioni del mio script?

Ecco lo script:

function multithreaded_curl(array $urls, $concurrent_urls = 50) 
    { 
     // Data to be returned 
     $total_results = array(); 

     // Chunk the URLs 
     $chunked_urls = array_chunk($urls, $concurrent_urls); 
     foreach ($chunked_urls as $chunked_url) { 
      // Chunked results 
      $results = array(); 

      // Array of cURL handles 
      $curl_handles = array(); 

      // Multi-handle 
      $mh = curl_multi_init(); 

      // Loop through $chunked_urls and create curl handles, then add them to the multi-handle 
      foreach ($chunked_url as $k => $v) { 
       $curl_handles[$k] = curl_init(); 

       curl_setopt($curl_handles[$k], CURLOPT_URL, $v); 
       curl_setopt($curl_handles[$k], CURLOPT_HEADER, 0); 
       curl_setopt($curl_handles[$k], CURLOPT_RETURNTRANSFER, 1); 
       curl_setopt($curl_handles[$k], CURLOPT_SSL_VERIFYPEER, 0); 

       curl_multi_add_handle($mh, $curl_handles[$k]); 
      } 

      // Execute the handles 
      $running = NULL; 
      do { 
       curl_multi_exec($mh, $running); 
      } while ($running > 0); 

      // Get content and remove handles 
      foreach ($curl_handles as $k => $v) { 
       $results[$k] = json_decode(curl_multi_getcontent($v), TRUE); 
       curl_multi_remove_handle($mh, $v); 
      } 

      // All done 
      curl_multi_close($mh); 

      // Combine results 
      $total_results = array_merge($total_results, $results); 
     } 

     return $total_results; 
    } 
+0

1 - non è multithreaded 2 - è probabilmente un timeout PHP che si raggiunge, non un limite di arricciamento effettivo –

+0

1. non è 'curl_multi_exec' multithreaded? 2. Ho 'set_time_limit (0);' eseguito prima di chiamare questa funzione. – StackOverflowNewbie

+0

Golang sarà utile qui: D facile concorrenza. – Lansana

risposta

4

riguardante Q1: Come già commentato, ci sono diverse opzioni per ottenere problemi con quella algoritmo. Prima di tutto, probabilmente esaurisce risorse locali (maniglie ecc.) E remote (maxConnections, maxThreads ecc.). Non farlo in questo modo.

relative a Q2: non è necessario (vedere di seguito), ma si prega di ottenere le risposte di errore prima di indovinare errori.

in merito a Q3: sì, esistono diverse opzioni sul server web REMOTE in base al fornitore del server Web remoto (limitazioni sui numeri di thread, numero massimo di connessioni, numero massimo di connessioni per client ecc.). Se anche questo è il tuo server, puoi regolarli per meglio soddisfare le tue esigenze, ma prima devi accordare l'algoritmo del cliente.

Nel complesso, non ha molto senso iniziare più di una manciata di connessioni alla volta. Il riutilizzo della connessione è molto più veloce e non rovina le maniglie locali ecc. E non esegue attacchi DOS ai sistemi remoti. L'unica causa di ciò è che il server ha bisogno di molto tempo per l'elaborazione delle richieste rispetto alle esigenze di io.

Hai controllato la velocità quando diciamo solo 4 connessioni alla volta e le riutilizziamo invece di crearne di nuove? Infatti stai popolando curl_handles [] per un singolo uso di ciascuno. La creazione di oggetti IO costa tempo.