it-swarm-tr.com

PHP uygulamalarında çoklu iş parçacığı nasıl kullanılır?

Gerçekten ya da sadece onu simüle ederek PHP içinde çok iş parçacıklı bir model uygulamanın gerçekçi bir yolu var mı? Bir süre önce, işletim sistemini PHP yürütülebilir dosyasının başka bir örneğini yükleyip başka eşzamanlı işlemleri yönetmeye zorlamanız önerildi.

Bununla ilgili sorun, PHP kodunun PHP örneğini çalıştırmayı tamamladığında, bellekte kalmasıdır, çünkü onu PHP içinden öldürmenin bir yolu yoktur. Bu yüzden birkaç ipliği simüle ediyorsanız, neler olacağını hayal edebilirsiniz. Bu yüzden hala PHP'den çoklu iş parçacıklı yapmanın veya etkin bir şekilde simüle edilmesinin bir yolunu arıyorum. Herhangi bir fikir?

366
Steve Obbayi

PHP'de çok diş açılabilir

Evet, PHP içinde pthreads ile çoklu iş parçacığını yapabilirsiniz

PHP belgelerine :

pthreads, PHP'de çoklu iş parçacığı için gerekli tüm araçları sağlayan nesne yönelimli bir API'dir. PHP uygulamalar Threads, Workers ve Threaded nesneleri oluşturabilir, okuyabilir, yazabilir, uygulayabilir ve senkronize edebilir.

Uyarı : pthreads uzantısı bir web sunucusu ortamında kullanılamaz. Bu nedenle PHP içindeki iş parçacığı yalnızca CLI tabanlı uygulamalarda kalmalıdır.

Basit Test

#!/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();
}

?>

İlk çalıştırma

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

İkinci çalıştırma

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

Gerçek Dünya Örneği

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);
}
391
Baba

neden kullanmıyorsun popen ?

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]);
    }
}
34
masterb

Threading, PHP'de mevcut değildir, ancak HTTP isteklerini asenkron çağrı olarak kullanarak eşzamanlı programlama yapmak mümkündür.

Kıvrılmanın zaman aşımı ayarı 1 olarak ayarlanmış ve birbiriyle ilişkilendirilmek istediğiniz işlemler için aynı session_id kullanılarak, aşağıdaki örnekteki gibi oturum değişkenleriyle iletişim kurabilirsiniz. Bu yöntemle tarayıcınızı bile kapatabilirsiniz ve eşzamanlı işlem sunucuda hala var.

Bunun gibi doğru oturum kimliğini doğrulamayı unutmayın:

http: //localhost/test/verifysession.php? sessionid = [the doğru kimlik]

startprocess.php

$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"];

process1.php

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);
}

verifysession.php

if ($_REQUEST["sessionid"])
    session_id($_REQUEST["sessionid"]);

session_start();
var_dump($_SESSION);

closeprocess.php

if ($_REQUEST["sessionid"])
    session_id($_REQUEST["sessionid"]);

session_start();
$_SESSION["closesession"] = true;
var_dump($_SESSION);
18
Ricardo

Sen iş parçacığı olamaz, ancak php bir derece süreç kontrolü var. Burada yararlı olan iki işlev kümesi:

Proses kontrol fonksiyonları http://www.php.net/manual/en/ref.pcntl.php

POSIX fonksiyonları http://www.php.net/manual/en/ref.posix.php

İşleminizi pcntl_fork ile - çocuğun PID'ını geri getirerek - çatallayabilirsiniz. O zaman bu PID'yi istemek için posix_kill kullanabilirsiniz.

Bununla birlikte, eğer bir ebeveyn sürecini öldürürseniz, çocuk sürecine ölmesini söyleyen bir sinyal gönderilmelidir. Eğer php'nin kendisi bunu tanımıyorsa, onu yönetmek için bir fonksiyon kaydedebilir ve pcntl_signal kullanarak temiz bir çıkış yapabilirsiniz.

11
J.D. Fitz.Gerald

Bunun eski bir soru olduğunu biliyorum ama arayan insanlar için, şimdi C [:PHP çoklu iş parçacığı yeteneği veren C dilinde yazılmış bir PECL uzantısı var, burada bulunuyor https://github.com/ krakjoe/pThreads

8
JasonDavis

diş ipi kullanımı, pintreads PECL eklentisi ile mümkün

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

8
pinkal vansia

Diş açmayı taklit edebilirsiniz. PHP arka plan işlemlerini popen (veya proc_open) aracılığıyla çalıştırabilir. Bu süreçler stdin ve stdout ile iletilebilir. Tabii ki bu süreçlerin kendisi bir php programı olabilir. Muhtemelen alacağın kadar yakın.

5
Pete

Bir komut satırı komut dosyası (örneğin php komut satırı) çalıştırmak için exec () kullanabilirsiniz ve çıktıyı bir dosyaya aktarırsanız, komut dosyanız komutun bitmesini beklemez.

PHP CLI sözdizimini tam olarak hatırlayamıyorum, ancak şöyle bir şey istersiniz:

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

Pek çok paylaşılan barındırma sunucusunun güvenlik nedeniyle varsayılan olarak exec () işlevinin devre dışı bırakıldığını düşünüyorum, ancak denemeye değer olabilir.

5
Adam Hopkinson

Pcntl_fork hakkında nasıl?

örnekler için kılavuz sayfamızı inceleyin: PHP pcntl_fork

3
Jarrod

Ne yapmaya çalıştığınıza bağlı olarak, bunu başarmak için curl_multi'yi de kullanabilirsiniz.

3
Sheldmandu

Bunun çok eski olduğunu biliyorum, ama bakabilirsin http://phpthreadlib.sourceforge.net/

İki yönlü dişler arası iletişimi destekler ve aynı zamanda çocuk dişlerini öldürmek için (yetimleri önleme) yerleşik korumalara sahiptir.

3
Unsigned

pcntl_forkgüvenli mod açıksa, web sunucusu ortamında çalışmaz. Bu durumda, sadece PHP'nin CLI versiyonunda çalışacaktır.

2
Stilero

Seçenek olabilir:

  1. multi_curl
  2. Biri aynı sistem komutunu kullanabilir
  3. İdeal senaryo, C dilinde bir diş açma işlevi oluşturmak ve PHP'yi derlemek/yapılandırmaktır. Şimdi bu fonksiyon PHP'nin fonksiyonu olacak.
2
Manoj Donga

Thread sınıfı , PECL pthreads ≥ 2.0.0'dan beri kullanılabilir.

2

Şu anki yorumumun yazılmasından beri, PHP konuları hakkında bilmiyorum. Buradaki cevabı kendim aramaya geldim, ancak geçici bir çözüm, isteği web sunucusundan alan PHP programının tüm cevap formülasyonunu çıktılarını depolayan bir konsol uygulamasına, cevabını ise cevaplayana bırakması. istek, bir ikili dosyaya ve konsol uygulamasını başlatan PHP programı, bu ikili dosyayı bayt byte'ını alınan talebe cevap olarak döndürür. Konsol uygulaması, OpenMP kullanan C++ programları da dahil olmak üzere uygun iş parçacığı desteği de dahil olmak üzere, sunucu üzerinde çalışan herhangi bir programlama dilinde yazılabilir.

Bir güvenilmez, kirli hile, bir konsol uygulamasını çalıştırmak için PHP kullanmak, "uname",

uname -a

ve sunucu yazılımının tam sürümünü bulmak için bu konsol komutunun çıktısını HTML çıktısına yazdırın. Ardından, aynı tam sürümünü bir VirtualBox örneğine yükleyin, istediğin tamamen bağımsız, tercihen statik olan ikili dosyaları derleyin/birleştirin ve sonra bunları sunucuya yükleyin. Bu noktadan sonra, PHP uygulaması, uygun çoklu iş parçacığı olan konsol uygulaması rolündeki bu ikili dosyaları kullanabilir. Sunucu yöneticisi sunucuya gerekli tüm programlama dili uygulamalarını yüklemediğinde, bu durum kirli, güvenilir olmayan bir geçici çözümdür. Dikkat edilmesi gereken şey, PHP uygulamasının konsol uygulamalarını aldığı her isteğin,/uygulamalarını/exit/get_killed komutlarını sonlandırmasıdır.

Barındırma hizmeti yöneticilerinin bu tür sunucu kullanım kalıpları hakkında ne düşündüklerine gelince, sanırım kültüre kayıyor. Kuzey Avrupa'da, servis sağlayıcı REKLAM EDİLEN NEDİR VEYA KOMPLE komutlarının yürütülmesine izin verildiyse ve kötü amaçlı olmayan dosyaların yüklenmesine izin verildiyse ve servis sağlayıcının birkaç dakika sonra veya 30 saniye sonra bile herhangi bir sunucu işlemini öldürme hakkı varsa daha sonra, barındırma hizmeti yöneticileri, uygun bir şikayet oluşturmak için herhangi bir argümandan yoksundur. Amerika Birleşik Devletleri ve Batı Avrupa'da, durum/kültür çok farklı ve ABD ve/veya Batı Avrupa'da, barındırma hizmeti sağlayıcısının, yukarıda açıklanan numarayı kullanan barındırma hizmeti istemcilere hizmet vermeyi reddetme ihtimalinin büyük olduğuna inanıyorum. Bu sadece benim tahminim, ABD'deki barındırma hizmetleri ile ilgili kişisel deneyimim ve Batı Avrupa'daki barındırma hizmetleri hakkında diğerlerinden duyduğum bilgileri verdi. Şu anki yorumumun yazılmasından itibaren (2018_09_01) Güney-Avrupa barındırma hizmeti sağlayıcılarının, Güney-Avrupa ağ yöneticilerinin kültürel normları hakkında hiçbir şey bilmiyorum.

0
Martin Vahi