it-swarm-vi.tech

Làm thế nào một người có thể sử dụng đa luồng trong các ứng dụng PHP

Có cách nào thực tế để triển khai mô hình đa luồng trong PHP dù thực sự hay chỉ mô phỏng nó. Đôi khi, có ý kiến ​​cho rằng bạn có thể buộc hệ điều hành tải một phiên bản khác của PHP có thể thực thi và xử lý các quy trình đồng thời khác.

Vấn đề với điều này là khi mã PHP thực hiện xong việc thực hiện PHP trong bộ nhớ vì không có cách nào để giết nó từ bên trong PHP. Vì vậy, nếu bạn đang mô phỏng một số chủ đề, bạn có thể tưởng tượng những gì sẽ xảy ra. Vì vậy, tôi vẫn đang tìm kiếm một cách đa luồng có thể được thực hiện hoặc mô phỏng hiệu quả từ bên trong PHP. Có ý kiến ​​gì không?

366
Steve Obbayi

Đa luồng có thể có trong php

Có, bạn có thể thực hiện đa luồng trong PHP với pthreads

Từ tài liệu PHP :

pthreads là một API hướng đối tượng, cung cấp tất cả các công cụ cần thiết cho đa luồng trong PHP. PHP ứng dụng có thể tạo, đọc, viết, thực thi và đồng bộ hóa với Chủ đề, Công nhân và Đối tượng có luồng.

Cảnh báo : Không thể sử dụng tiện ích mở rộng pthreads trong môi trường máy chủ web. Do đó, luồng trong PHP chỉ nên duy trì cho các ứng dụng dựa trên CLI.

Kiểm tra đơn giản

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

?>

Chạy đầu tiên

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

Lần chạy thứ hai

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

Ví dụ về thế giới thực

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

tại sao bạn không sử dụng 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

Việc phân luồng không có sẵn trong kho PHP, nhưng có thể lập trình đồng thời bằng cách sử dụng các yêu cầu HTTP như các cuộc gọi không đồng bộ.

Với cài đặt thời gian chờ của curl được đặt thành 1 và sử dụng cùng session_id cho các quy trình bạn muốn được liên kết với nhau, bạn có thể giao tiếp với các biến phiên như trong ví dụ của tôi dưới đây. Với phương pháp này, bạn thậm chí có thể đóng trình duyệt của mình và quy trình đồng thời vẫn tồn tại trên máy chủ.

Đừng quên xác minh ID phiên chính xác như thế này:

http: //localhost/test/verifysession.php? Sessionid = [the id chính xác]

start process.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);

close process.php

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

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

Trong khi bạn không thể xử lý, bạn có một số mức độ kiểm soát quy trình trong php. Hai bộ hàm hữu ích ở đây là:

Các chức năng kiểm soát quy trình http://www.php.net/manual/en/ref.pcntl.php

Các hàm POSIX http://www.php.net/manual/en/ref.poseix.php

Bạn có thể kết thúc quá trình của mình với pcntl_fork - trả lại PID của con. Sau đó, bạn có thể sử dụng posix_kill để giải quyết vấn đề đó.

Điều đó nói rằng, nếu bạn giết một quá trình cha mẹ, một tín hiệu sẽ được gửi đến tiến trình con bảo nó chết. Nếu chính php không nhận ra điều này, bạn có thể đăng ký một chức năng để quản lý nó và thực hiện một lối thoát sạch bằng pcntl_signal.

11
J.D. Fitz.Gerald

Tôi biết đây là một câu hỏi cũ nhưng đối với những người tìm kiếm, có một phần mở rộng PECL được viết bằng C cung cấp khả năng đa luồng PHP bây giờ, nó nằm ở đây https://github.com/ krakjoe/pthreads

8
JasonDavis

sử dụng các chủ đề được thực hiện bởi phần mở rộng PECL của pthreads

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

8
pinkal vansia

Bạn có thể mô phỏng luồng. PHP có thể chạy các quy trình nền thông qua popen (hoặc Proc_open). Những quá trình này có thể được giao tiếp thông qua stdin và stdout. Tất nhiên các quá trình đó có thể tự là một chương trình php. Đó có thể là gần như bạn sẽ nhận được.

5
Pete

Bạn có thể sử dụng exec () để chạy tập lệnh dòng lệnh (chẳng hạn như dòng lệnh php) và nếu bạn chuyển đầu ra thành một tệp thì tập lệnh của bạn sẽ không đợi lệnh kết thúc.

Tôi không thể nhớ cú pháp php CLI, nhưng bạn muốn một cái gì đó như:

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

Tôi nghĩ rằng khá nhiều máy chủ lưu trữ chia sẻ đã bị exec () bị tắt theo mặc định vì lý do bảo mật, nhưng có thể đáng để thử.

5
Adam Hopkinson

Làm thế nào về pcntl_fork?

kiểm tra trang hướng dẫn của chúng tôi để biết ví dụ: PHP pcntl_fork

3
Jarrod

Tùy thuộc vào những gì bạn đang cố gắng làm, bạn cũng có thể sử dụng curl_multi để đạt được nó.

3
Sheldmandu

Tôi biết điều này đã cũ, nhưng bạn có thể nhìn vào http://phpthreadlib.sourceforge.net/

Nó hỗ trợ giao tiếp giữa các luồng hai chiều và cũng có các biện pháp bảo vệ tích hợp để tiêu diệt các luồng con (ngăn trẻ mồ côi).

3
Unsigned

pcntl_fork sẽ không hoạt động trong môi trường máy chủ web nếu có chế độ an toàn được bật. Trong trường hợp này, nó sẽ chỉ hoạt động trong phiên bản CLI của PHP.

2
Stilero

Bạn có thể có tùy chọn:

  1. đa_curl
  2. Người ta có thể sử dụng lệnh hệ thống cho cùng
  3. Kịch bản lý tưởng là, tạo một hàm luồng trong ngôn ngữ C và biên dịch/cấu hình trong PHP. Bây giờ chức năng đó sẽ là chức năng của PHP.
2
Manoj Donga

Lớp luồng khả dụng vì pthreads PECL ≥ 2.0.0.

2
Dhananjay Kashyap

Khi viết bình luận hiện tại của tôi, tôi không biết về các chủ đề PHP. Tôi đã tự mình tìm kiếm câu trả lời, nhưng một cách giải quyết là chương trình PHP nhận được yêu cầu từ máy chủ web ủy thác toàn bộ công thức trả lời cho ứng dụng bảng điều khiển lưu trữ đầu ra của nó, câu trả lời cho yêu cầu, đối với tệp nhị phân và chương trình PHP đã khởi chạy ứng dụng bảng điều khiển trả về tệp nhị phân từng byte đó làm câu trả lời cho yêu cầu nhận được. Ứng dụng bàn điều khiển có thể được viết bằng bất kỳ ngôn ngữ lập trình nào chạy trên máy chủ, bao gồm cả những ngôn ngữ có hỗ trợ luồng phù hợp, bao gồm các chương trình C++ sử dụng OpenMP.

Một mẹo không đáng tin cậy, bẩn thỉu là sử dụng PHP để thực thi một ứng dụng bảng điều khiển, "uname",

uname -a

và in đầu ra của lệnh console đó sang đầu ra HTML để tìm ra phiên bản chính xác của phần mềm máy chủ. Sau đó cài đặt cùng một phiên bản phần mềm cho phiên bản VirtualBox, biên dịch/lắp ráp bất cứ thứ gì hoàn toàn khép kín, tốt nhất là tĩnh, nhị phân mà người ta muốn và sau đó tải chúng lên máy chủ. Từ thời điểm đó trở đi, ứng dụng PHP có thể sử dụng các nhị phân đó trong vai trò của ứng dụng giao diện điều khiển có đa luồng thích hợp. Đó là một cách giải quyết tình huống bẩn thỉu, không đáng tin cậy, khi quản trị viên máy chủ chưa cài đặt tất cả các cài đặt ngôn ngữ lập trình cần thiết cho máy chủ. Điều cần chú ý là ở mọi yêu cầu, ứng dụng PHP nhận được (các) ứng dụng bảng điều khiển chấm dứt/exit/get_kills.

Đối với những gì các quản trị viên dịch vụ lưu trữ nghĩ về các kiểu sử dụng máy chủ như vậy, tôi đoán nó sẽ sôi sục với văn hóa. Ở Bắc Âu, nhà cung cấp dịch vụ ĐÃ GIAO HÀNG TUYỆT VỜI LÀ GÌ QUẢNG CÁO và nếu việc thực thi lệnh console được cho phép và tải lên các tệp không phải phần mềm độc hại được cho phép và nhà cung cấp dịch vụ có quyền giết bất kỳ quy trình máy chủ nào sau vài phút hoặc thậm chí sau 30 giây , sau đó các quản trị viên dịch vụ lưu trữ thiếu bất kỳ đối số nào để hình thành một khiếu nại thích hợp. Ở Hoa Kỳ và Tây Âu, tình hình/văn hóa rất khác nhau và tôi tin rằng rất có thể ở Hoa Kỳ và/hoặc Tây Âu, nhà cung cấp dịch vụ lưu trữ sẽ từ chối phục vụ khách hàng sử dụng dịch vụ lưu trữ sử dụng thủ thuật được mô tả ở trên. Đó chỉ là phỏng đoán của tôi, dựa trên kinh nghiệm cá nhân của tôi với các dịch vụ lưu trữ của Hoa Kỳ và đưa ra những gì tôi đã nghe từ những người khác về dịch vụ lưu trữ Tây Âu. Khi viết bình luận hiện tại của tôi (2018_09_01) tôi không biết gì về các chuẩn mực văn hóa của các nhà cung cấp dịch vụ lưu trữ Nam-Âu, quản trị viên mạng Nam-Âu.

0
Martin Vahi