코루틴
코루틴은 스레드보다 더 경량화된 사용자 수준의 병행성 메커니즘으로, 프로세스 내에서 다중 작업 스케줄링을 구현할 수 있습니다. 코루틴 간의 전환은 수동으로 일시 중지 및 복원을 제어하여 이루어지며, 프로세스 컨텍스트 스위칭의 오버헤드를 피할 수 있습니다.
workerman은 하위에서 자동으로 Swoole/Swow/Fiber 드라이버와 호환되는 범용 코루틴 인터페이스를 제공합니다.
팁
이 기능은 workerman>=5.1.0이 필요합니다.
주의
- 코루틴은
SwooleSwowFiber드라이버만 지원합니다. Fiber드라이버를 사용할 경우composer require revolt/event-loop을 설치해야 합니다.Swoole또는Swow드라이버는 PHP 블로킹 함수 자동 코루틴화를 통해 기존의 동기 코드를 비동기적으로 실행할 수 있습니다.- 그러나
Fiber는Swoole와Swow처럼 자동으로 코루틴화할 수 없으며, PHP 내장 블로킹 함수에 직면했을 때 전체 프로세스를 블로킹하여 코루틴 전환이 발생하지 않습니다. SwooleSwowFiber드라이버를 사용하는 경우,workerman은 매번onWorkerStartonMessageonConnectonClose등의 콜백을 실행할 때 자동으로 코루틴을 생성합니다.$worker->eventLoop=xxx;를 사용해 서로 다른worker에 대해 다른 코루틴 드라이버를 설정할 수 있습니다.
<?php
use Workerman\Connection\TcpConnection;
use Workerman\Coroutine;
use Workerman\Events\Swoole;
use Workerman\Events\Fiber;
use Workerman\Protocols\Http\Request;
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
$worker1 = new Worker('http://0.0.0.0:8001');
$worker1->eventLoop = Swoole::class; // Swoole 코루틴 사용
$worker1->onMessage = function (TcpConnection $connection, Request $request) {
Coroutine::create(function () {
echo file_get_contents("http://www.example.com/event/notify");
});
$connection->send('ok');
};
$worker2 = new Worker('http://0.0.0.0:8001');
$worker2->eventLoop = Fiber::class; // 내장 Fiber 코루틴 사용
$worker2->onMessage = function (TcpConnection $connection, Request $request) {
Coroutine::create(function () {
echo file_get_contents("http://www.example.com/event/notify");
});
$connection->send('ok');
};
Worker::runAll();
코루틴이 제공하는 인터페이스
interface CoroutineInterface
{
/**
* 코루틴 생성 후 즉시 실행
*/
public static function create(callable $callable, ...$data): CoroutineInterface;
/**
* 코루틴 실행 시작
*/
public function start(mixed ...$args): mixed;
/**
* 코루틴 실행 복구
*/
public function resume(mixed ...$args): mixed;
/**
* 코루틴 ID 가져오기
*/
public function id(): int;
/**
* 코루틴 파괴 시의 콜백 설정
*/
public static function defer(callable $callable): void;
/**
* 현재 코루틴 일시 정지
*/
public static function suspend(mixed $value = null): mixed;
/**
* 현재 코루틴 가져오기
*/
public static function getCurrent(): CoroutineInterface|Fiber|SwowCoroutine|static;
/**
* 현재가 코루틴 환경인지 판단
*/
public static function isCoroutine(): bool;
}
코루틴에 대하여
장점
PHP에서 코루틴을 도입한 가장 큰 효과는 동기 방식으로 비동기 코드를 작성할 수 있어 콜백 지옥을 피하고 코드 가독성과 유지 보수성을 높일 수 있다는 것입니다.
코루틴은 IO 집약적인 비즈니스의 탄력을 크게 향상시킬 수 있으며, 비교적 적은 프로세스에서 더 큰 처리량을 제공할 수 있습니다.
단점
하지만 코루틴을 도입한 후 개발자는 전역 변수 오염, 자원 경쟁, 타사 라이브러리 수정 등 여러 문제에 주의해야 하며, 개발 및 유지 관리 비용이 증가하고 정신적 부담이 분명히 증가합니다.
코루틴을 도입하면서 코루틴 생성, 스케줄링, 파괴, 연결 풀 등 추가 오버헤드가 발생합니다. 대량의 부하 테스트 데이터에 따르면, CPU를 충분히 활용하는 상황에서 코루틴을 도입한 후 최대 성능이 블로킹 IO보다 약 10%-20% 감소합니다.