Visualizzazione dei risultati da 1 a 10 su 10
  1. #1
    Utente di HTML.it
    Registrato dal
    Aug 2003
    Messaggi
    80

    multi-threading & web services

    Voglio crere un'applicazione PHP multithread.

    Il proxy deve eseguire le richieste ai web services in maniera parallela.
    Usando pcntl_fork(), posso forkare il processo padre, e nei figli svolgere le chiamate ai web services. Ma come faccio a restituire i valori restituiti da tali chiamate al processo padre?
    In C la risposta sarebbe: "Usa una pipe e dup2()". Ma in PHP non riesco a trovare documentazione che mi aiuti a capire come fare.
    Il problema si può semplificare così: "Come si fa ad eseguire una dup2 in PHP?"

  2. #2
    Utente di HTML.it L'avatar di M4rko
    Registrato dal
    Dec 2000
    Messaggi
    619
    In PHP non esiste multithreading, infatti tu stesso parli di fork

    Ad ogni modo dai un'occhiata qui per qualche spunto:
    http://php.html.it/articoli/leggi/90...ema-con-php/1/

    Tutti hanno bisogno di credere in qualcosa.
    Io credo che mi farò un'altra birra.


  3. #3
    Utente di HTML.it
    Registrato dal
    Aug 2003
    Messaggi
    80
    ok...
    esatto uso le fork perchè non esiste il multithreading in PHP.
    Ho letto tutta la sezione riguardo all'IPC in PHP, dal quale risulta che l'unico modo per comunicare tra padre e figlio è la memoria condivisa.
    Quindi la shared memory è l'unica soluzione?

  4. #4
    beh no, puoi usare (e anzi te le consiglio) le socket unix

    cmq per dup2 e pipe te ne esci molto più semplicemente avendo un mono processo e usando le funzioni di proc_* asincrone

    http://it.php.net/manual/it/function.proc-open.php

  5. #5
    Originariamente inviato da daniele_dll
    beh no, puoi usare (e anzi te le consiglio) le socket unix
    Esatto puoi usare le socket pair. La shared memory è un bel casino da gestire, soprattutto per le race condition.

  6. #6
    Utente di HTML.it
    Registrato dal
    Aug 2003
    Messaggi
    80
    Ho scritto questa porzione di codice che fa uso di proc_open per eseguire i processi, ma non mi sembra eseguano in parallelo...

    codice:
    <?php
    
    $descriptorspec = array(
    0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
    1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
    2 => array("file", "/tmp/error-output.txt", "a") // stderr is a file to write to
    );
    
    $process1 = proc_open('php client_mangiare_dormire.php', $descriptorspec, $pipes1);
    $process2 = proc_open('php client_percorsi.php', $descriptorspec, $pipes2);
    $process3 = proc_open('php client_monumenti_opere.php', $descriptorspec, $pipes3);
    
    echo stream_get_contents($pipes1[1]);
    fclose($pipes1[1]);
    echo stream_get_contents($pipes2[1]);
    fclose($pipes2[1]);
    echo stream_get_contents($pipes3[1]);
    fclose($pipes3[1]);
    
    // It is important that you close any pipes before calling
    // proc_close in order to avoid a deadlock
    proc_close($process1);
    proc_close($process2);
    proc_close($process3);
    ?>
    Infatti se metto una sleep(2); nel file client_mangiare_dormire.php, il programma si ferma per 2 secondi, invece di eseguire gli altri 2 script.
    Come faccio a rendere il tutto asincrono?

  7. #7
    Utente di HTML.it
    Registrato dal
    Aug 2003
    Messaggi
    80
    Ottimo!
    Ce l'ho fatta!

    Alla fine ho utilizzato le fork e le socket. Praticamente creo una pair con
    codice:
    $ary1 = array();
    
    if (!socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $ary1)) {
    	echo socket_strerror(socket_last_error());
    }
    Poi faccio tre fork annidate con
    codice:
    $pid = pcntl_fork();
    
    if ($pid == -1) {
    	echo 'Could not fork Process.';
    }
    elseif($pid == 0)
    {
    ...
    }
    else{
    ...
    }
    nei processi figli scrivo sulla socket
    codice:
    $str = callMangiareDormire();
    	socket_close($ary1[0]);
    	if (!socket_write($ary1[1], $str, strlen($str))) {
    		echo socket_strerror(socket_last_error());
    	}
    	socket_close($ary1[1]);
    e nel padre leggo dalla socket
    codice:
    socket_close($ary1[1]);
    
    			pcntl_wait($stato);
    			if ($str1 = socket_read($ary1[0], 1000000, PHP_BINARY_READ)) {
    				echo "Recieved $str1\n";
    			}
    In questa maniera la procedura risulta completamente parallela, consentendomi di chiamare contemporanemente 3 web services.

  8. #8
    Utente di HTML.it
    Registrato dal
    Aug 2003
    Messaggi
    80
    Ho trovato un piccolo problema...
    Quando tento di far funzionare il processo proxy come servizio web, cioè da una chiamata del tipo:
    codice:
    $client = new SoapClient("eventi.wsdl",array("trace" => 1,"exceptions" => 1));
    $lista_eventi = $client->getEventi();
    dove getEventi è definito nel file wsdl come ws_eventi.php,
    ottengo questo errore:
    SoapFault exception: [SOAP-ENV:Server] Call to undefined function pcntl_fork()

    Mentre se eseguo test_socket.php oppure test_web_service.php separatamente non ho problemi, tranne il fatto, ovviamente, che l'intero processo non è in parallelo.

    Per eseguire test_socket.php devo utilizzare il CLI non il browser, quindi digitando da shell il comando:
    php test_socket.php, mentre il web services lo eseguo direttamente da browser. Potrebbe essere questo il problema?

  9. #9
    probabilmente si, però lo puoi aggirare startando lo script php da console (via script web chiami il file .php tramite l'interprete php)

  10. #10
    Utente di HTML.it
    Registrato dal
    Aug 2003
    Messaggi
    80
    Esatto! Se scrivo:
    codice:
    $pipe = popen("php test_socket.php","r");
    $str = fread($pipe,100000);
    pclose($pipe1);
    ottengo nel browser lo stesso risulotato della console.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.