PHP 응용 프로그램에서 다중 스레딩을 사용하려면 어떻게 해야 합니까?
PHP에서 멀티 스레드 모델을 구현할 수 있는 현실적인 방법이 있습니까, 아니면 단순히 시뮬레이트할 수 있습니까?옛날에는 운영체제가 PHP 실행 파일의 다른 인스턴스를 로드하고 다른 동시 프로세스를 처리하도록 강제할 수 있다고 제안되었습니다.
문제는 PHP 코드가 PHP 인스턴스의 실행을 마쳤을 때 PHP 인스턴스는 PHP 내에서 종료할 방법이 없기 때문에 메모리에 남아 있다는 것입니다.따라서 여러 스레드를 시뮬레이션하면 어떤 일이 일어날지 상상할 수 있습니다.그래서 저는 여전히 PHP 내에서 효과적으로 멀티 스레딩을 수행하거나 시뮬레이트할 수 있는 방법을 찾고 있습니다.좋은 생각 있어요?
php에서 멀티스레딩 가능
네, PHP에서 pthreads로 멀티스레딩을 할 수 있습니다.
pthreads는 PHP에서 멀티스레딩에 필요한 모든 도구를 제공하는 객체 지향 API입니다.PHP 애플리케이션은 스레드, 워커 및 스레드 개체를 생성, 읽기, 쓰기, 실행 및 동기화할 수 있습니다.
경고:pthreads 확장은 웹 서버 환경에서 사용할 수 없습니다.따라서 PHP의 스레드화는 CLI 기반 응용 프로그램에만 있어야 합니다.
심플 테스트
#!/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);
}
왜 팝펜을 안 써?
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]);
}
}
스레드화는 PHP 재고에서 사용할 수 없지만 HTTP 요청을 비동기 호출로 사용하여 동시 프로그래밍이 가능합니다.
컬의 타임아웃 설정을 1로 설정하고 서로 관련짓는 프로세스에 동일한 session_id를 사용하면 아래 예시와 같이 세션 변수와 통신할 수 있습니다.이 방법을 사용하면 브라우저를 닫을 수도 있고 동시 프로세스가 서버에 계속 존재합니다.
다음과 같이 올바른 세션 ID를 확인하는 것을 잊지 마십시오.
프로세스를 시작합니다.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"];
프로세스1.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);
}
검증.php
if ($_REQUEST["sessionid"])
session_id($_REQUEST["sessionid"]);
session_start();
var_dump($_SESSION);
클로즈 프로세스php
if ($_REQUEST["sessionid"])
session_id($_REQUEST["sessionid"]);
session_start();
$_SESSION["closesession"] = true;
var_dump($_SESSION);
스레드는 할 수 없지만 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을 사용하여 완전히 종료할 수 있습니다.
스레드 사용은 pthreads PECL 확장에 의해 가능합니다.
http://www.php.net/manual/en/book.pthreads.php
오래된 질문인 것은 알지만, 검색하시는 분들을 위해 PECL 확장자가 C로 쓰여져 있습니다.이 확장자는, PHP 멀티 컨버전스 기능을 제공하고 있습니다.https://github.com/krakjoe/pthreads에 있습니다.
exec()을 사용하여 명령줄 스크립트(명령줄 php 등)를 실행할 수 있으며 출력을 파일로 파이핑하면 스크립트는 명령어가 완료될 때까지 기다리지 않습니다.
php CLI 구문은 잘 기억나지 않지만 다음과 같은 것이 필요합니다.
exec("/path/to/php -f '/path/to/file.php' | '/path/to/output.txt'");
보안상의 이유로 디폴트로는 exec()이 비활성화되어 있는 공유 호스팅 서버도 적지 않다고 생각합니다만, 시도해 볼 만한 가치가 있을지도 모릅니다.
스레드를 시뮬레이트할 수 있습니다.PHP는 popen(또는 proc_open)을 통해 백그라운드 프로세스를 실행할 수 있습니다.이러한 프로세스는 stdin 및 stdout을 통해 통신할 수 있습니다.물론 이러한 프로세스 자체는 php 프로그램이 될 수 있습니다.그것은 아마 당신이 얻을 수 있는 가장 가까운 것입니다.
다음의 옵션을 사용할 수 있습니다.
- 복수_패킷
- 같은 용도로 system 명령어를 사용할 수 있습니다.
- 이상적인 시나리오는 스레드화 함수를 C 언어로 만들고 PHP로 컴파일/구성하는 것입니다.이제 그 함수는 PHP의 함수가 됩니다.
pcntl_fork는 어떻습니까?
매뉴얼 페이지에서 예를 확인하세요: PHP pcntl_fork
<?php
$pid = pcntl_fork();
if ($pid == -1) {
die('could not fork');
} else if ($pid) {
// we are the parent
pcntl_wait($status); //Protect against Zombie children
} else {
// we are the child
}
?>
리눅스 서버를 사용하는 경우,
exec("nohup $php_path path/script.php > /dev/null 2>/dev/null &")
아르그 좀 건네주실래요?
exec("nohup $php_path path/script.php $args > /dev/null 2>/dev/null &")
대본으로.php
$args = $argv[1];
또는 Symfony https://symfony.com/doc/current/components/process.html 를 사용합니다.
$process = Process::fromShellCommandline("php ".base_path('script.php'));
$process->setTimeout(0);
$process->disableOutput();
$process->start();
어떤 작업을 수행하느냐에 따라 curl_multi를 사용하여 작업을 수행할 수도 있습니다.
pcntl_fork
는, 세이프 모드가 설정되어 있는 경우, Web 서버 환경에서는 동작하지 않습니다.이 경우 PHP의 CLI 버전에서만 작동합니다.
오래된 질문인 것은 알지만, 많은 사람에게 도움이 될 것입니다.PHPThreads
코드 예:
function threadproc($thread, $param) {
echo "\tI'm a PHPThread. In this example, I was given only one parameter: \"". print_r($param, true) ."\" to work with, but I can accept as many as you'd like!\n";
for ($i = 0; $i < 10; $i++) {
usleep(1000000);
echo "\tPHPThread working, very busy...\n";
}
return "I'm a return value!";
}
$thread_id = phpthread_create($thread, array(), "threadproc", null, array("123456"));
echo "I'm the main thread doing very important work!\n";
for ($n = 0; $n < 5; $n++) {
usleep(1000000);
echo "Main thread...working!\n";
}
echo "\nMain thread done working. Waiting on our PHPThread...\n";
phpthread_join($thread_id, $retval);
echo "\n\nOur PHPThread returned: " . print_r($retval, true) . "!\n";
PHP 확장자 필요:
- 인식하다
- pcntl
- 소켓
나는 이 도서관을 몇 달 동안 운영 중에 사용하고 있다.POSIX pthreads를 사용하는 것 같은 느낌을 주기 위해 많은 노력을 기울였습니다.pthreads에 익숙하다면, 이것을 집어서 즉시 매우 효과적으로 사용할 수 있습니다.
계산상 내부 작용은 상당히 다르지만, 실제로는 의미론과 구문을 포함하여 기능이 거의 동일합니다.
높은 throughput 레이트를 지원하는 매우 효율적인 Web Socket 서버를 작성하기 위해 사용하고 있습니다.미안해요, 횡설수설해요.나는 내가 마침내 그것을 출시했다는 것에 흥분하고 그것이 누구에게 도움이 될지 보고 싶어!
멀티스레딩은 여러 작업 또는 프로세스를 동시에 실행하는 것을 의미하며, 우리는 다음 코드를 사용하여 이를 달성할 수 있습니다. 비록 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로
현재 코멘트를 쓰고 있는 시점에서는 PHP 스레드에 대해서는 모릅니다.제가 직접 답변을 찾으러 왔습니다만, 한 가지 해결 방법은 웹 서버로부터 요청을 수신한 PHP 프로그램이 전체 응답 식을 콘솔 애플리케이션에 위임하여 요청에 대한 답변인 출력을 바이너리 파일에 저장하고 콘솔 애플리케이션을 실행한 PHP 프로그램이 바이너리 파일을 반환하는 것입니다.수신된 요구에 대한 응답으로 te-by-byte를 지정합니다.콘솔 애플리케이션은 OpenMP를 사용하는 C++ 프로그램을 포함하여 적절한 스레드화를 지원하는 프로그래밍 언어를 포함하여 서버에서 실행되는 모든 프로그래밍 언어로 작성할 수 있습니다.
신뢰할 수 없는 더러운 트릭 중 하나는 콘솔 애플리케이션 "uname"을 실행하기 위해 PHP를 사용하는 것입니다.
uname -a
이 콘솔 명령어의 출력을 HTML 출력으로 출력하여 서버 소프트웨어의 정확한 버전을 확인합니다.그런 다음 Virtual Box 인스턴스에 동일한 버전의 소프트웨어를 설치하고 필요한 완전 자급자족 바이너리를 컴파일/어셈블하여 서버에 업로드합니다.이 시점부터 PHP 애플리케이션은 적절한 멀티스레딩을 갖춘 콘솔애플리케이션의 역할로 바이너리를 사용할 수 있습니다.서버 관리자가 필요한 프로그래밍 언어 구현을 서버에 모두 설치하지 않은 경우, 이는 더럽고 신뢰할 수 없는 회피책입니다.주의해야 할 것은 PHP 어플리케이션이 콘솔 어플리케이션을 수신할 때마다 terminates/exit/get_killed라는 것입니다.
이러한 서버 이용 패턴에 대해 호스팅 서비스 관리자가 어떻게 생각하는지, 그것은 문화로 귀결된다고 생각합니다.북유럽에서는 서비스 프로바이더가 애드버타이즈된 것을 제공해야 합니다.콘솔 명령어 실행과 말웨어 이외의 파일 업로드가 허용되고 서비스 프로바이더가 서버 프로세스를 몇 분 또는 30초 후에 종료할 수 있는 권한이 있는 경우 호스팅 서비스 관리자는 formi를 위한 어떠한 주장도 없습니다.적절한 불만을 제기합니다.미국과 서유럽에서는 상황/문화가 매우 다르며, 미국이나 서유럽에서는 호스팅 서비스 프로바이더가 위에서 설명한 방법을 사용하는 호스팅 서비스 클라이언트의 서비스를 거부할 가능성이 높다고 생각합니다.미국 호스팅 서비스에 대한 제 개인적인 경험과 서유럽 호스팅 서비스에 대해 다른 사람들로부터 들은 것을 고려할 때 그건 제 추측일 뿐입니다.현재의 코멘트(2018_09_01)의 작성 시점에서는, 남유럽의 호스팅 서비스 프로바이더, 남유럽의 네트워크 관리자의 문화 규범에 대해서는 아무것도 모릅니다.
언급URL : https://stackoverflow.com/questions/70855/how-can-one-use-multi-threading-in-php-applications
'programing' 카테고리의 다른 글
파일 핸들을 사용하여 파일 이름 가져오기(또는 파일 삭제) (0) | 2023.01.02 |
---|---|
JavaScript 개체: 이름으로 변수 속성에 문자열로 액세스합니다. (0) | 2023.01.02 |
MySQL 쉼표로 구분된 두 테이블 결합 (0) | 2023.01.02 |
JFrame 아이콘 변경 방법 (0) | 2023.01.02 |
MariaDB: 수십억 개의 레코드를 갱신하는 최적의 방법 (0) | 2023.01.02 |