コルーチン
コルーチンは、スレッドよりも軽量なユーザーレベルの同時実行メカニズムであり、プロセス内でのマルチタスクスケジューリングを実現します。コルーチン間の切り替えを手動で停止および再開することで、プロセスのコンテキストスイッチのオーバーヘッドを回避します。
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%低下します。