PHP 비동기식에 대한 지식은 여전히 매우 혼란스럽습니다. 이를 정리하기 위해 이 글을 작성하고 있습니다.
전통적인 php-fpm 프로세스가 요청을 실행할 때 동일한 동시성을 달성하기 위해 생성되어야 하는 프로세스 수입니다. 더 나쁜 점은 각 요청을 다시 컴파일하고 실행해야 하기 때문에 동시성이 전혀 증가하지 않는다는 것입니다. 따라서 Swoole의 출현과 WorkerMan은 중국에서 널리 사용되는 두 가지 상주 메모리 프레임워크입니다[1]. 이 두 프레임워크의 원칙은 이벤트 루프를 사용하여 프로그램을 메모리에 유지하고 외부 요청을 기다리며 높은 동시성을 달성하는 것입니다.
비동기인 이유
먼저 예제를 살펴보겠습니다
작업 디렉터리에 새 파일 SlowServer.php를 만듭니다.
<?php sleep(5); // 5秒后才能返回请求 echo 'done';
서비스를 활성화합니다.
$ php -S localhost:8081 slowServer.php
다른 터미널을 열고 종속성을 설치합니다
$ pecl install event # 安装 event 扩展 $ composer require workerman/workerman $ composer require react/http-client:^0.5.9
새 파일 만들기 Worker.php
require_once __DIR__ . '/vendor/autoload.php'; use Workerman\Worker; use Workerman\Connection\AsyncTcpConnection; use Amp\Artax\Response; $http_worker = new Worker("http://0.0.0.0:8082"); $http_worker->count = 1; // 只开一个进程 $http_worker->onMessage = function($connection, $host) { echo 1; $data = file_get_contents('http://localhost:8081'); $connection->send($data); }; Worker::runAll();
서버 열기
php worker.php start
브라우저에서 두 개의 탭을 열고 URL http://localhost:8082를 엽니다. 이때 터미널은 "1"을 출력하고 잠시 후 다시 "1"을 출력하는 것을 볼 수 있는데, 그 이유는 첫 번째 요청을 처리할 때 8081 서버가 8081 반환을 기다리는 동안 차단되었기 때문입니다. 요청이 완료되면 두 번째 요청 처리가 시작됩니다. 즉, php-fpm과 마찬가지로 동일한 수의 동시성을 달성하려면 요청이 하나씩 실행되어야 합니다. 이제 코드를 수정하세요
$http_worker->onMessage = function($connection, $host) { echo 1; $loop = Worker::getEventLoop(); $client = new \React\HttpClient\Client($loop); $request = $client->request('GET', 'http://localhost:8081'); $request->on('error', function(Exception $e) use ($connection) { $connection->send($e); }); $request->on('response', function ($response) use ($connection) { $response->on('data', function ($data) use ($connection) { $connection->send($data); }); }); $request->end(); };
이제 서비스를 열고 브라우저에서 요청을 시작하세요. 요청 직후 두 번째 "1"이 출력되고 첫 번째 요청이 아직 종료되지 않은 것으로 나타났습니다. 이는 프로세스가 더 이상 차단되지 않으며 동시성 양이 프로세스 수가 아닌 CPU 및 메모리에 따라 달라짐을 나타냅니다.
비동기가 필요한 이유
위의 예에서 이미 명확해졌습니다. Reactphp 프레임워크는 http 요청을 비동기화하고 onMessage 함수를 비차단화하여 CPU가 다음 요청을 처리할 수 있도록 합니다. 즉, CPU 루프는 8081이 반환될 때까지 기다리다가 epoll 대기로 전환됩니다.
비동기의 의미는 IO 대기에서 CPU를 해방하고 다른 컴퓨팅 작업을 처리할 수 있다는 것입니다. 비동기 구현을 위해 프레임워크를 사용하는 방법을 알고 싶다면 여기를 읽어보세요. ReactPHP 또는 자체 AsyncTcpConnection과 결합된 WorkerMan은 이미 많은 io 요청의 비동기 요구 사항을 충족할 수 있습니다. 이러한 프레임워크가 어떻게 비동기식인지 계속 논의하겠습니다.
어느 곳을 비동기화해야 하는지
위의 예를 통해 일단 실행에 CPU가 필요하지 않지만 io를 기다릴 때는 io 프로세스를 비동기화해야 한다는 것을 이미 알고 있습니다.
이벤트 루프 구현
위의 예에서는 http 요청을 비동기식으로 전환하기 위해 Reactphp를 사용합니다. 실제로 WorkerMan 프레임워크 자체도 비동기적으로 onMessage 함수를 활성화하는 방법을 살펴보겠습니다. 먼저, 다음 파일을 생성합니다.
이 글의 기초가 되는 "php가 epoll을 사용한다" 전에 글을 쓴 적이 있습니다. 해당 기사에서는 이벤트 콜백이 타이밍, 즉
<?php $context = stream_context_create(); $socket = stream_socket_server('tcp://0.0.0.0:8081', $errno, $errmsg, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN,$context); // 注册一个 fd(file descriptor) function react($socket){ $new_socket = stream_socket_accept($socket, 0, $remote_address); echo 1; } $eventBase = new EventBase(); $event = new Event($eventBase, $socket, Event::READ | Event::PERSIST, 'react', $socket); // 注册一个事件,检测 fd 有没有写入内容 $event->add(); $eventBase->loop(); // 开始循环
을 통해 구현됩니다. 여기서 이벤트 콜백은 fd가 콘텐츠를 작성했는지 여부를 감지하여 구현됩니다. 이 프로세스에는 CPU의 참여가 필요하지 않습니다. fd에 쓰여진 내용이 있으면 'react' 함수가 호출되고 CPU가 사용되기 시작합니다. 이때 프로세스가 또 다른 비동기 요청(예를 들어, Reactphp 프레임워크를 사용하여 웹페이지를 요청하는 등)을 실행하면 프로그램은 CPU를 해제합니다. 이때 또 다른 요청이 들어오면 콜백하여 또 다른 '반응' 기능을 실행할 수 있습니다. 이는 동시성의 양을 증가시킵니다.
Coroutine
Generater
이것은 생성기의 PHP 공식 문서입니다. http://php.net/manual/zh/lang...
$ php react.php
코루틴이 무엇인가요?
위 프로그램을 작성하는 또 다른 방법입니다. istelnet 127.0.0.1 8081
코루틴 및 비동기
코루틴이 중단될 수 있으므로 프로그램이 요청을 시작한 후에 이벤트 루프를 시작한 다음 Yield를 사용하여 반환하면 프로그램이 계속해서 메인 프로그램 부분을 실행합니다. 이벤트가 반환되고 함수가 트리거되고 Generatot가 실행되어 코루틴 부분을 계속 실행합니다. 캡슐화 후에는 비동기 콜백 함수가 없는 것처럼 보이며 이는 동기 함수와 매우 유사합니다. 이제 코루틴을 캡슐화하는 두 가지 프레임워크인 ampphp와 swoole이 있습니다. 관심이 있다면 이에 대해 알아볼 수 있습니다.위 내용은 PHP에 비동기 프로그래밍이 필요한 이유는 무엇입니까? PHP 비동기 프로그래밍에 대한 자세한 설명(예제 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!