복붙노트

어떻게 PHP 응용 프로그램에서 멀티 스레딩을 사용할 수 있습니까?

PHP

어떻게 PHP 응용 프로그램에서 멀티 스레딩을 사용할 수 있습니까?

PHP에서 멀티 스레드 모델을 구현하는 현실적인 방법이 있든 없든 실제로 시뮬레이션하는 것입니다. 얼마 전 다시 운영 체제가 PHP 실행 파일의 다른 인스턴스를로드하고 다른 동시 프로세스를 처리하도록 할 수 있다고 제안되었습니다.

이 문제는 PHP 코드가 실행을 마쳤을 때 PHP 인스턴스에서 메모리를 죽일 방법이 없기 때문에 PHP 인스턴스가 메모리에 남아 있다는 것입니다. 따라서 여러 스레드를 시뮬레이트하는 경우 일어날 일을 상상할 수 있습니다. 그래서 나는 멀티 스레딩이 PHP 내에서 효과적으로 수행되거나 시뮬레이션 될 수있는 방법을 찾고 있습니다. 어떤 아이디어?

해결법

  1. ==============================

    1.

    예, pthread를 사용하여 PHP에서 멀티 스레딩을 할 수 있습니다.

    PHP 문서에서 :

    간단한 테스트

    #!/usr/bin/php
    <?php
    class AsyncOperation extends Thread {
    
        public function __construct($arg) {
            $this->arg = $arg;
        }
    
        public function run() {
            if ($this->arg) {
                $sleep = mt_rand(1, 10);
                printf('%s: %s  -start -sleeps %d' . "\n", date("g:i:sa"), $this->arg, $sleep);
                sleep($sleep);
                printf('%s: %s  -finish' . "\n", date("g:i:sa"), $this->arg);
            }
        }
    }
    
    // Create a array
    $stack = array();
    
    //Initiate Multiple Thread
    foreach ( range("A", "D") as $i ) {
        $stack[] = new AsyncOperation($i);
    }
    
    // Start The Threads
    foreach ( $stack as $t ) {
        $t->start();
    }
    
    ?>
    

    첫 번째 실행

    12:00:06pm:     A  -start -sleeps 5
    12:00:06pm:     B  -start -sleeps 3
    12:00:06pm:     C  -start -sleeps 10
    12:00:06pm:     D  -start -sleeps 2
    12:00:08pm:     D  -finish
    12:00:09pm:     B  -finish
    12:00:11pm:     A  -finish
    12:00:16pm:     C  -finish
    

    두 번째 실행

    12:01:36pm:     A  -start -sleeps 6
    12:01:36pm:     B  -start -sleeps 1
    12:01:36pm:     C  -start -sleeps 2
    12:01:36pm:     D  -start -sleeps 1
    12:01:37pm:     B  -finish
    12:01:37pm:     D  -finish
    12:01:38pm:     C  -finish
    12:01:42pm:     A  -finish
    

    실제 세계의 예

    error_reporting(E_ALL);
    class AsyncWebRequest extends Thread {
        public $url;
        public $data;
    
        public function __construct($url) {
            $this->url = $url;
        }
    
        public function run() {
            if (($url = $this->url)) {
                /*
                 * If a large amount of data is being requested, you might want to
                 * fsockopen and read using usleep in between reads
                 */
                $this->data = file_get_contents($url);
            } else
                printf("Thread #%lu was not provided a URL\n", $this->getThreadId());
        }
    }
    
    $t = microtime(true);
    $g = new AsyncWebRequest(sprintf("http://www.google.com/?q=%s", rand() * 10));
    /* starting synchronization */
    if ($g->start()) {
        printf("Request took %f seconds to start ", microtime(true) - $t);
        while ( $g->isRunning() ) {
            echo ".";
            usleep(100);
        }
        if ($g->join()) {
            printf(" and %f seconds to finish receiving %d bytes\n", microtime(true) - $t, strlen($g->data));
        } else
            printf(" and %f seconds to finish, request failed\n", microtime(true) - $t);
    }
    
  2. ==============================

    2.

    왜 포핀을 사용하지?

    for ($i=0; $i<10; $i++) {
        // open ten processes
        for ($j=0; $j<10; $j++) {
            $pipe[$j] = popen('script2.php', 'w');
        }
    
        // wait for them to finish
        for ($j=0; $j<10; ++$j) {
            pclose($pipe[$j]);
        }
    }
    
  3. ==============================

    3.

    스레딩은 주식 PHP에서 사용할 수 없지만 HTTP 요청을 비동기 호출로 사용하면 동시 프로그래밍이 가능합니다.

    curl의 timeout 설정을 1로 설정하고 서로 연결하려는 프로세스에 대해 동일한 session_id를 사용하면 아래 예에서와 같이 세션 변수와 통신 할 수 있습니다. 이 방법을 사용하면 브라우저를 닫을 수도 있고 동시 프로세스가 서버에 계속 존재할 수도 있습니다.

    다음과 같이 올바른 세션 ID를 확인하는 것을 잊지 마십시오.

    $request = "http://localhost/test/process1.php?sessionid=".$_REQUEST["PHPSESSID"];
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $request);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 1);
    curl_exec($ch);
    curl_close($ch);
    echo $_REQUEST["PHPSESSID"];
    
    set_time_limit(0);
    
    if ($_REQUEST["sessionid"])
       session_id($_REQUEST["sessionid"]);
    
    function checkclose()
    {
       global $_SESSION;
       if ($_SESSION["closesession"])
       {
           unset($_SESSION["closesession"]);
           die();
       }
    }
    
    while(!$close)
    {
       session_start();
       $_SESSION["test"] = rand();
       checkclose();
       session_write_close();
       sleep(5);
    }
    
    if ($_REQUEST["sessionid"])
        session_id($_REQUEST["sessionid"]);
    
    session_start();
    var_dump($_SESSION);
    
    if ($_REQUEST["sessionid"])
        session_id($_REQUEST["sessionid"]);
    
    session_start();
    $_SESSION["closesession"] = true;
    var_dump($_SESSION);
    
  4. ==============================

    4.

    당신이 스레드 할 수없는 동안, 당신은 PHP에서 어느 정도의 프로세스 제어를 가지고 있습니다. 여기서 유용한 두 가지 함수 세트는 다음과 같습니다.

    프로세스 제어 기능 http://www.php.net/manual/en/ref.pcntl.php

    POSIX 함수 http://www.php.net/manual/en/ref.posix.php

    pcntl_fork를 사용하여 프로세스를 포크 할 수 있습니다. 하위 PID를 반환합니다. 그런 다음 posix_kill을 사용하여 해당 PID를 폐기 할 수 있습니다.

    즉, 부모 프로세스를 죽이는 경우 자식 프로세스에 신호를 보내서 죽이라는 내용을 전달해야합니다. PHP 자체가 이것을 인식하지 못한다면, 관리 할 함수를 등록하고 pcntl_signal을 사용하여 깨끗한 종료를 할 수 있습니다.

  5. ==============================

    5.

    thread를 사용하는 것은 pthreads PECL 확장에 의해 가능해진다.

    http://www.php.net/manual/en/book.pthreads.php

  6. ==============================

    6.

    이 질문은 오래된 질문이지만 사람들이 검색 할 때 PECL 확장이 C로 작성되어 PHP 멀티 스레딩 기능을 제공합니다. https://github.com/krakjoe/pthreads에 있습니다.

  7. ==============================

    7.

    스레딩을 시뮬레이트 할 수 있습니다. PHP는 popen (또는 proc_open)을 통해 백그라운드 프로세스를 실행할 수 있습니다. 이러한 프로세스는 stdin 및 stdout을 통해 통신 할 수 있습니다. 물론 그 프로세스 자체가 PHP 프로그램이 될 수 있습니다. 아마 당신이 얻는만큼 가깝습니다.

  8. ==============================

    8.

    exec ()를 사용하여 명령 행 스크립트 (예 : 명령 행 php)를 실행할 수 있으며, 출력을 파일로 파이프하면 스크립트는 명령이 완료 될 때까지 기다리지 않습니다.

    php CLI 구문을 기억할 수는 없지만 다음과 같은 것을 원합니다.

    exec("/path/to/php -f '/path/to/file.php' | '/path/to/output.txt'");
    

    보안상의 이유로 기본적으로 exec ()가 비활성화 된 공유 호스팅 서버가 있다고 생각하지만 시도해 볼만한 가치가 있습니다.

  9. ==============================

    9.

    당신이하고자하는 것에 따라 curl_multi를 사용하여 그것을 달성 할 수도 있습니다.

  10. ==============================

    10.

    이 방법은 오래되었지만 http://phpthreadlib.sourceforge.net/에서 볼 수 있습니다.

    그것은 양방향 스레드 간 통신을 지원하고 자식 스레드를 없애기위한 보호 기능을 내장하고 있습니다 (고아 방지).

  11. ==============================

    11.

    다음 옵션 중 하나를 선택할 수 있습니다.

  12. ==============================

    12.

    PCntl_fork는 어떻습니까?

    매뉴얼 페이지에서 예제를 확인하십시오 : PHP pcntl_fork

  13. ==============================

    13.

    Thread 클래스는 PECL pthreads가 2.0.0 이상이므로 사용할 수 있습니다.

  14. ==============================

    14.

    안전 모드가 켜져 있으면 pcntl_fork가 웹 서버 환경에서 작동하지 않습니다. 이 경우 PHP CLI 버전에서만 작동합니다.

  15. ==============================

    15.

    GuzzleHttp를 사용하여 HTTP 멀티 스레딩을 할 경우 (웹 응용 프로그램에서 pthread가 작동하지 않을 수 있으므로) 아래 블로그를 참조하십시오 - https://blog.madewithlove.be/post/concurrent-http-requests/

  16. ==============================

    16.

    현재의 코멘트를 쓰는 시점에서 PHP 스레드에 대해 알지 못합니다. 내가 직접 대답을 찾겠다는 하나의 해결책은 웹 서버로부터 요청을받는 PHP 프로그램이 응답 결과를 저장하는 콘솔 애플리케이션에 전체 응답 공식을 위임하여 요청에 대한 응답을 바이너리 파일에 저장하는 것이다 콘솔 응용 프로그램을 시작한 PHP 프로그램은 수신 된 요청에 대한 응답으로 이진 파일을 바이트 단위로 반환합니다. 콘솔 응용 프로그램은 OpenMP를 사용하는 C ++ 프로그램을 포함하여 적절한 스레딩 지원을 포함하여 서버에서 실행되는 모든 프로그래밍 언어로 작성할 수 있습니다.

    하나의 신뢰할 수없고, 더러운, 속임수는 PHP를 사용하여 콘솔 응용 프로그램 "uname"을 실행하는 것입니다.

    uname -a
    

    해당 콘솔 명령의 출력을 HTML 출력에 인쇄하여 서버 소프트웨어의 정확한 버전을 찾으십시오. 그런 다음 VirtualBox 인스턴스에 정확히 같은 버전의 소프트웨어를 설치하고, 원하는 모든 자체 포함, 바람직하게는 정적 바이너리를 컴파일 및 어셈블 한 다음 서버에 업로드하십시오. 이 시점부터 PHP 응용 프로그램은 적절한 멀티 스레딩이있는 콘솔 응용 프로그램의 역할에서 해당 바이너리를 사용할 수 있습니다. 서버 관리자가 필요한 프로그래밍 언어 구현을 서버에 모두 설치하지 않은 상황을 해결할 수있는 더럽고 신뢰할 수없는 해결 방법입니다. 주의해야 할 점은 PHP 애플리케이션이 콘솔 애플리케이션을 수신 할 때마다 / exit / get_killed가 종료된다는 것입니다.

    호스팅 서비스 관리자가 그러한 서버 사용 패턴을 어떻게 생각하는지에 관해서는 문화로 귀결됩니다. 북유럽에서는 서비스 제공 업체가 무엇을 제공했는지, 그리고 콘솔 명령의 실행이 허용되고 맬웨어가 아닌 파일의 업로드가 허용되고 서비스 제공 업체가 몇 분 또는 30 초 후에 서버 프로세스를 종료 할 수있는 권리가있는 경우 , 호스팅 서비스 관리자는 적절한 불만을 제기하는 것에 대한 어떠한 주장도하지 않습니다. 미국과 서유럽에서 상황 / 문화는 매우 다르며 미국 및 / 또는 서유럽에서 호스팅 서비스 제공 업체가  위에서 설명한 트릭을 사용하는 호스팅 서비스 클라이언트를 제공하는 것을 거부합니다. 그것은 미국의 호스팅 서비스에 대한 개인적인 경험과 서유럽 호스팅 서비스에 대해 다른 사람들로부터 들었던 것을 생각해 볼 때 제 추측입니다. 현재의 의견 (2018_09_01)을 쓰는 시점에서 나는 남유럽 호스팅 서비스 제공자 인 남유럽 네트워크 관리자의 문화적 규범에 대해서는 아무것도 모른다.

  17. ==============================

    17.

    나는 뭔가를 놓쳤을 수도 있지만 임원은 나를 위해 비동기로 Windows 환경에서 다음과 같은 윈도우에서 사용되는 매력이 작동하지 않았다;)

    $script_exec = "c:/php/php.exe c:/path/my_ascyn_script.php";
    
    pclose(popen("start /B ". $script_exec, "r"));
    
  18. ==============================

    18.

    멀티 스레딩은 여러 작업이나 프로세스를 동시에 수행한다는 것을 의미합니다. PHP에서 멀티 스레딩을 직접 수행 할 방법은 없지만 다음과 같은 방법으로 거의 동일한 결과를 얻을 수 있습니다.

    chdir(dirname(__FILE__));  //if you want to run this file as cron job
     for ($i = 0; $i < 2; $i += 1){
     exec("php test_1.php $i > test.txt &");
     //this will execute test_1.php and will leave this process executing in the background and will go         
    
     //to next iteration of the loop immediately without waiting the completion of the script in the   
    
     //test_1.php , $i  is passed as argument .
    

    }

    Test_1.php

    $conn=mysql_connect($host,$user,$pass);
    $db=mysql_select_db($db);
    $i = $argv[1];  //this is the argument passed from index.php file
    for($j = 0;$j<5000; $j ++)
    {
    mysql_query("insert  into  test   set
    
                    id='$i',
    
                    comment='test',
    
                    datetime=NOW() ");
    
    }
    

    이렇게하면 test_1.php가 동시에 두 번 실행되며 두 프로세스가 백그라운드에서 동시에 실행되므로 PHP로 다중 스레드를 구현할 수 있습니다.

    이 사람은 정말 좋은 일을 PHP에서 멀티 쓰레딩

  19. from https://stackoverflow.com/questions/70855/how-can-one-use-multi-threading-in-php-applications by cc-by-sa and MIT lisence