Как стать автором
Обновить

Попытка реализации многопоточности в PHP

Чулан
Задача была в след: Нужно было получить координаты для множества городов и регионов.
Т.к. координат было куча возникло решение в многопоточности.

Плюсы: одновременное выполнение нескольких запросов к серверу.
Минусы: если запускать свой скрипт, то надо указывать url к скрипту, т.е. на локале не всегда будет работать.

Итак, сам класс:

<?php
/**************************************************************************************
class:    Thread using curl_multi 
version:  1.0 alfa
Author:    Sect0R
email:    odruslan@gmail.com
**************************************************************************************/

class thread
{
  
  var $Urls;
  var $ReturnHeaders;
  var $FollowLocation;
  var $CookiesFile;
  var $ReturnValues;
  var $Errors;
  var $LastIndex;
  var $Header;
  var $Proxyes;
  var $POST;
  var $UserAgent;
  var $ConnectionTimeout;
  
  function Thread($UrlList = array()){
    $this->Urls = $UrlList;
    $this->ReturnHeaders = 0;
    $this->FollowLocation = 1;
    $this->CookiesVar = 'CookiesFile';
    $this->ReturnValues = array();
    $this->LastIndex = 0;
    $this->ConnectionTimeout = 20;
    $this->POST = array();
    $this->Proxyes = array();
    
      // Addition headers
    $this->UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.7.12) Gecko/20050919 Firefox/1.0.7" ;
    $this->Header [] = "Accept: text/html;q=0.9, text/plain;q=0.8, image/png, */*;q=0.5" ;
    $this->Header [] = "Accept_charset: windows-1251, utf-8, utf-16;q=0.6, *;q=0.1";
    $this->Header [] = "Accept_encoding: identity";
    $this->Header [] = "Accept_language: en-us,en;q=0.5";
    $this->Header [] = "Connection: close";
    $this->Header [] = "Cache-Control: no-store, no-cache, must-revalidate";
    $this->Header [] = "Keep_alive: 300";
    $this->Header [] = "Expires: Thu, 01 Jan 1970 00:00:01 GMT";
  }
  
  function normalize_url($url) {
      $url = trim($url);
      if (!preg_match('/http\:\/\//i',$url))
        $url = 'http://'.$url;
      return $url;
  }
    
  function AddUrl($url,$proxy = false) { // Add URL to List
    $this->Urls[$this->LastIndex] = $this->normalize_url($url);
    $this->Proxyes[$this->LastIndex] = $proxy;
    $this->LastIndex ++;
  }
  
  function CheckAll() { // Check All params
    // check file
    if (!file_exists($this->CookiesFile)) {
      $f = fopen($this->CookiesFile,"w");
      var_dump($f);
         fwrite($f,'');
         fclose($f);
      @chmod($this->CookiesFile,0777);
    }
  }
  
  
  function Run() { //Run process and return array with errors and results
      // Set PHP Variables
      @set_time_limit(0);
      @ignore_user_abort(true);
      @ini_set('memory_limit','512M');
      
        $this->CheckAll();
      
    $conn = array();
    print_r($this->Urls);
    $mh = curl_multi_init();
      foreach ($this->Urls as $i=>$url) {
        $conn[$i] = curl_init($url);
        if (!empty($this->Proxyes[$i]))
          @curl_setopt  ( $conn[$i] , CURLOPT_PROXY , $this->Proxyes[$i]);
        if (!empty($this->POST[$i])) {
          curl_setopt  ( $conn[$i] , CURLOPT_POST , 1);
          curl_setopt  ( $conn[$i] , CURLOPT_POSTFIELDS , http_build_query($this->POST[$i]));
        }
          @curl_setopt ( $conn[$i] , CURLOPT_FOLLOWLOCATION, $this->FollowLocation);
          @curl_setopt ( $conn[$i] , CURLOPT_CONNECTTIMEOUT, $this->ConnectionTimeout);
          @curl_setopt ( $conn[$i] , CURLOPT_RETURNTRANSFER, 1);
          @curl_setopt ( $conn[$i] , CURLOPT_HEADER, $this->ReturnHeaders);
          curl_setopt ( $conn[$i] , CURLOPT_COOKIEJAR, $this->CookiesFile);
            curl_setopt ( $conn[$i] , CURLOPT_COOKIEFILE, $this->CookiesFile);
          @curl_setopt ( $conn[$i] , CURLOPT_USERAGENT , $this->UserAgent );
          @curl_setopt ( $conn[$i] , CURLOPT_HTTPHEADER , $this->Header );
        curl_multi_add_handle ($mh,$conn[$i]);
      }
    // start performing the request
      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);
       }
    }
       // if Main Error
    if ($mrc != CURLM_OK) {
       return "Curl multi read error $mrc";
    }
    
    foreach ($this->Urls as $i => $url) {
         if (($err = curl_error($conn[$i])) == '') //if no errors
         {
          $this->ReturnValues[$i] = curl_multi_getcontent($conn[$i]);
         } else// if error
           $this->Errors[$i] = $err; 
         }
       curl_multi_remove_handle($mh,$conn[$i]); //delete handle
       curl_close($conn[$i]); // close curl
    }
    
  curl_multi_close($mh); // close main curl
  unset($mh);
  
    return $this->ReturnValues;
  }
  
}
?>


* This source code was highlighted with Source Code Highlighter.


Ну и конечно тестирование:

<?php
$key = 'ABQIAAAAvPNKWsMGkmBeEsDOoHgLdBSlbMpHBbUVNY3iJpEhFSJCDcfQ1xSmosIIEHIwaN2v4JrRtuvHp4G6LA';

$name1 = 'Belarus,Minsk';
$name2 = 'Belarus,Grodno';
$name3 = 'USA,New York';

$request1 = "http://maps.google.com/maps/geo?q=".urlencode(trim($name1))."&output=csv&key={$key}";
$request2 = "http://maps.google.com/maps/geo?q=".urlencode(trim($name2))."&output=csv&key={$key}";
$request3 = "http://maps.google.com/maps/geo?q=".urlencode(trim($name3))."&output=csv&key={$key}";

include_once("thread.class.php");

$thread = new thread;

  $thread->AddUrl($request1);
  $thread->AddUrl($request2);
  $thread->AddUrl($request3);
  $thread->ReturnHeaders = 0;
  $thread->CookiesFile = getcwd().'/cook';

// Run timer
$begin_time = time();
  $result = $thread->Run();

echo '<pre>';
echo "RUNNING: ".(time()-$begin_time)." sec<br>";
echo "RESULT:<br>";
print_r($result);
echo "<br><br>ERRORS:<br>";
print_r($thread->Errors);
echo '</pre>';
?>


* This source code was highlighted with Source Code Highlighter.
Теги:
Хабы:
Всего голосов 11: ↑5 и ↓6 -1
Просмотры 266
Комментарии Комментарии 23