1.5 アップグレードガイド
バックアップを取った後、次のコマンドを実行してアップグレードします
composer require workerman/webman-framework ^1.5 -W && composer require webman/console ^1.2.12 && php webman install
機能の特性と変更
workerman v5のcoroutineをサポートしています
ヒント
workerman v5 は PHP>=8.1 が必要です
workermanアップグレードコマンドcomposer require workerman/workerman ^5.0.0 -W
Fiber coroutine を使用するためにはcomposer require revolt/event-loop ^1.0.0
をインストールする必要があります
サンプル
遅延応答
<?php
namespace app\controller;
use support\Request;
use Workerman\Timer;
class TestController
{
public function index(Request $request)
{
// 1.5秒待機
Timer::sleep(1.5);
return $request->getRemoteIp();
}
}
Timer::sleep()
はPHPのsleep()
関数と似ていますが、Timer::sleep()
はプロセスをブロックしません
HTTPリクエストの発行
注意
composer require workerman/http-client ^2.0.0
をインストールする必要があります
<?php
namespace app\controller;
use support\Request;
use Workerman\Http\Client;
class TestController
{
public function index(Request $request)
{
static $client;
$client = $client ?: new Client();
$response = $client->get('http://example.com'); // 同期的に非同期リクエストを行う
return $response->getBody()->getContents();
}
}
同様に$client->get()
のリクエストはブロックされず、これによりwebmanで非同期リクエストを処理することができ、パフォーマンスが向上します。
詳細についてはworkerman/http-clientを参照してください。
support\Context クラスの追加
support\Context クラスは、リクエストに関連するデータを保存するために使用され、リクエストが完了すると、対応するコンテキストデータは自動的に削除されます。つまり、コンテキストデータのライフサイクルはリクエストのライフサイクルに従います。
グローバル変数の汚染
コルーチン環境では、リクエストに関連する状態情報をグローバル変数や静的変数に保存しないでください。なぜなら、これはグローバル変数の汚染を引き起こす可能性があるからです。例えば
<?php
namespace app\controller;
use support\Request;
use Workerman\Timer;
class TestController
{
protected static $name = '';
public function index(Request $request)
{
static::$name = $request->get('name');
Timer::sleep(5);
return static::$name;
}
}
プロセス数を1に設定し、連続して2つのリクエストを行った場合
http://127.0.0.1:8787/test?name=lilei
http://127.0.0.1:8787/test?name=hanmeimei
期待される結果はそれぞれ lilei
と hanmeimei
ですが、実際の結果は hanmeimei
です。
これは、2つ目のリクエストが静的変数$name
を上書きしたためです。最初のリクエストが完了すると、静的変数$name
は既にhanmeimei
になっているからです。
正しい方法は、リクエスト状態のデータをcontextに保存することです
<?php
namespace app\controller;
use support\Request;
use support\Context;
use Workerman\Timer;
class TestController
{
public function index(Request $request)
{
Context::set('name', $request->get('name'));
Timer::sleep(5);
return Context::get('name');
}
}
ローカル変数はデータの汚染を引き起こしません
<?php
namespace app\controller;
use support\Request;
use support\Context;
use Workerman\Timer;
class TestController
{
public function index(Request $request)
{
$name = $request->get('name');
Timer::sleep(5);
return $name;
}
}
$name
はローカル変数であるため、コルーチン間でローカル変数を参照することはできません。したがって、ローカル変数の使用はコルーチンの安全性を保証します。
コルーチンについて
コルーチンは銀の弾丸ではありません。コルーチンを導入すると、グローバル変数/静的変数の汚染に注意する必要があり、コンテキストを設定する必要があります。さらに、コルーチン環境でのバグのデバッグは、ブロック式プログラミングよりもやや複雑になります。
webmanのブロック式プログラミングは実際には十分に速く、techempower.comの最近の3年間のベンチマークデータによると、webmanのブロック式プログラミングはデータベースビジネスにおいてgoのwebフレームワークginやechoなどよりほぼ倍のパフォーマンスを持ち、伝統的なフレームワークlaravelよりも約40倍の高性能を示しています。
データベースやredisがすべて内部ネットワーク上にある場合、多プロセスのブロック式プログラミングの性能はしばしばコルーチンの導入よりも高くなります。なぜならば、データベースやredisなどが十分に速い場合、コルーチンの作成、スケジューリング、破棄のオーバーヘッドがプロセスの切り替えのオーバーヘッドよりも大きくなる可能性があるからです。そのため、このような場合には、コルーチンを導入してもパフォーマンスの向上がそれほど大きくないことが多いです。
いつコルーチンを使用するか
業務で遅いリクエストがある場合、例えば、ビジネスがサードパーティのAPIにアクセスする必要がある場合、workerman/http-clientを使用して非同期HTTP呼び出しを行うことで、アプリケーションの並行能力を向上させることができます。