Administrare server open source

Platforma de hosting cu software liber, gratuit, open source.

PHP este folosit de obicei ca limbaj server-side pentru generarea de continut dinamic in cadrul siteurilor, dar asta nu ne impiedica sa il folosim in construirea de aplicatii complexe si cu putina indemanare il putem folosi chiar si pentru crearea de aplicatii care in mod normal sunt dezvoltate in limbaje de programare consacrate cum ar fi C sau C++ – ex. daemoni sau aplicatii care proceseza in mod direct date, fara a exista o mediere din partea unui server web.

Pentru acest gen de aplicatii avem nevoie si de tehnici ceva mai avansate, cum ar fi procesarea in paralel. Crearea de fire de executie ne permite sa procesam mai multe date in acelasi timp, cel mai mare avantaj fiind scaderea timpului de rulare in cazul procesarii masive de date.

In cazul unei aplicatii care are de procesat 500 de URL-uri folosind libraria CURL daca timpul mediu de acces e de 0.5s pe o accesare avem nevoie de 250s pentru finalizarea acestora. Daca folosim in schimb 2 fire de executie putem procesa concomitent 2 URL-uri scazand timpul de procesare la jumatate. Bineinteles, in functie de configuratia hardware folosita si de complexitatea task-urilor se poate lucra si pe mai multe fire de executie.

Pentru exemplificare vom folosi scriptul de mai jos:

<?php
 
define("MAXPROC", 8); 
 
$isParent = true;      
$kids     = array();   
 
for( $i=0 ; (( $i<MAXPROC ) && $isParent ) ; $i++ ) { 
    $pid = pcntl_fork();
 
    if( $pid > 0 ) {
        $kids[] = $pid;
        printf("Kid number %d with PID[%d]\n", $i, $pid);
    } elseif( $pid == 0 ) {
        $isParent = false; 
        // Aici urmeaza codul de rulat in cadrul proceselor copil
    } else { 
        printf("Nu s-a putut crea procesul copil.\n");
    }
 
}
 
if( $isParent ) {
    $status = null;
    while( count($kids) ) {
        pcntl_wait( $status );
        array_pop( $kids );
    }
}
 
?>

Procesele paralele sunt initializate folosind functia pcntl_fork() in cadrul unei bucle for(;;) care va fi rulata de MAXPROC ori. Folosind pcntl_fork() vom crea practic o alta instanta a scriptului care va rula acelasi cod, iar pentru control trebuie sa gasim o metoda prin care sa facem diferenta intre procesul parinte care are rol de gestionare si procesele copil care vor rula codul necesar – accesari folosind CURL, ca sa mentinem exemplul mai sus amintit.

Pentru inceput definim constanta MAXPROC pe care o folosim ca limita pentru numarul de procesari. Variabila $isParent e folosita ca sa identificam daca scriptul este rulat in procesul parinte (are valoarea true) sau intr-un proces copil (are valoarea false) iar variabila $kids va contine lista de PID-uri a proceselor copil.

Bucla for( $i=0 ; (( $i<MAXPROC ) && $isParent ) ; $i++ ) e cea in cadrul careia vor fi initializate procesele copil. Pentru a ne asigura este rulata doar in procesul parinte, nu si in procesele copil, folosim variabila $isParent. In cadrul buclei variabila va lua valoarea false, ceea ce va determina scriptul sa nu ruleze bucla daca suntem in cadrul unui proces copil.

In bucla initializam un proces copil folosind pcntl_fork() si folosim codul de mai jos pentru a face diferenta intre procese:

    if( $pid > 0 ) {
        $kids[] = $pid;
        printf("Kid number %d with PID[%d]\n", $i, $pid);
    } elseif( $pid == 0 ) {
        $isParent = false; 
        // Aici urmeaza codul de rulat in cadrul proceselor copil
    } else { 
        printf("Nu s-a putut crea procesul copil.\n");
    }

Variabila $pid va avea valoarea returnata de pcntl_fork() care poate fi -1 in caz de eroare (nu se poate crea un proces nou) sau o valoare mai mare de 0 care va fi PID-ul procesului copil in cazul in care inca suntem in procesul parinte. Daca $pid are valoarea 0 suntem in procesul copil, deci vom da variabilei $isParent valoarea false pentru a nu fi rulata din nou bucla for(;;) care ar putea la randul ei sa initializeze alte fire de executie.

Ca sa evitam crearea de procese zombie, care continua sa ruleze dupa ce procesul parinte s-a oprit, vom rula in instanta parinte urmatorul cod:

if( $isParent ) {
    $status = null;
    while( count($kids) ) {
        pcntl_wait( $status );
        array_pop( $kids );
    }
}

Variabila $kids va contine toate PID-urile proceselor copil iar codul de mai sus, folosind functia pcntl_wait(), va astepta pana cand fiecare proces este incheiat inainte de a opri procesul parinte.

Astfel, folosind codul de mai sus, putem initializa mai multe procese copil inserand codul necesar dupa linia $isParent = false;. Procesele copil vor fi rulate in paralel ruland codul necesar iar procesul parinte va fi folosit doar pentru a le gestiona.

PHP

4 Responses so far.

  1. Inchireri autoutilitare says:

    mereu gasesc cate ceva folositor pe blogul acesta, tine-o tot asa.

  2. Andone Miclaus says:

    Multumesc pentru toate aceste coduri. Blog-ul tau mi-a fost de mare ajutor.

  3. Sergiu Tot says:

    Multumesc de aprecieri! Sunt binevenite 😉

  4. Despre monitoare says:

    Esti de mare ajutor cu acest Blog.