スムーズな再起動の原理

スムーズな再起動とは?

スムーズな再起動は、通常の再起動とは異なり、ユーザーに影響を与えることなくサービスを再起動することができます(一般的に短いリンクの業務を指します)。これにより、PHPプログラムを再読み込みし、業務コードの更新を完了することが可能です。

スムーズな再起動は、業務の更新やバージョンのリリースプロセスで一般的に使用され、コードのリリースによるサービスの再起動による一時的なサービスの利用不可の影響を避けることができます。

注意
Windowsシステムはreloadをサポートしていません。

注意
長い接続(例えばwebsocket)業務では、プロセスがスムーズに再起動されると接続が切断されます。解決策は、gatewayWorkerのようなアーキテクチャを使用することです。一組のプロセスが接続を維持し、このプロセスのreloadable属性をfalseに設定します。業務ロジックは別の一組のworkerプロセスを起動して処理し、gatewayとworkerプロセスはtcp通信の方法で相互に呼び出します。業務に変更が必要な場合は、workerプロセスだけを再起動すればよいのです。

制限

注意:on{...}コールバック内で読み込まれたファイルのみがスムーズな再起動後に自動的に更新されます。起動スクリプト内で直接読み込まれたファイルやハードコーディングされたコードは再起動しても自動更新されません。

以下のコードはreload後に更新されません

$worker = new Worker('http://0.0.0.0:1234');
$worker->onMessage = function($connection, $request) {
    $connection->send('hi'); // ハードコーディングされたコードはホット更新をサポートしていません
};
$worker = new Worker('http://0.0.0.0:1234');
require_once __DIR__ . '/your/path/MessageHandler.php'; // 起動スクリプトで直接読み込まれたファイルはホット更新をサポートしていません
$messageHandler = new MessageHandler();
$worker->onMessage = [$messageHandler, 'onMessage']; // MessageHandlerクラスにonMessageメソッドがあると仮定します

以下のコードはreload後に自動的に更新されます

$worker = new Worker('http://0.0.0.0:1234');
$worker->onWorkerStart = function($worker) { // onWorkerStartはプロセス起動後にトリガーされるコールバックです
    require_once __DIR__ . '/your/path/MessageHandler.php'; // プロセス起動後に読み込まれたファイルはホット更新をサポートしています
    $messageHandler = new MessageHandler();
    $worker->onMessage = [$messageHandler, 'onMessage'];
};

MessageHandler.phpを変更した後にphp start.php reloadを実行すると、MessageHandler.phpが再度メモリに読み込まれ、ビジネスロジックが更新されます。

ヒント
上記のコードはデモ用にrequire_once文を使用していますが、プロジェクトがpsr4オートローディングをサポートしている場合にはrequire_once文を呼び出す必要はありません。

スムーズな再起動の原理

Workermanは主プロセスと子プロセスに分かれており、主プロセスは子プロセスを監視し、子プロセスはクライアントからの接続と接続上のリクエストデータを受け取り、適切に処理してクライアントにデータを返します。業務コードが更新されると、実際には子プロセスを更新するだけでコードの更新が達成されます。

Workermanの主プロセスがスムーズな再起動信号を受信すると、主プロセスは特定の子プロセスに安全終了信号を送信します(対応するプロセスが現在のリクエストを処理した後に終了すること)。このプロセスが終了すると、主プロセスは新しい子プロセスを再作成します(この子プロセスは新しいPHPコードを読み込んでいます)。その後、主プロセスは再び別の古いプロセスに停止命令を送ります。このようにして、プロセスを一つずつ再起動していき、すべての古いプロセスが置き換えられるまで続行されます。

スムーズな再起動は、実際には古い業務プロセスを一つずつ終了させて、新しいプロセスを逐次作成することで実現されています。スムーズな再起動中にユーザーに影響を与えないようにするためには、プロセス内にユーザー関連の状態情報を保存しないことが求められます。つまり、業務プロセスはできるだけ無状態であることが望ましく、プロセスの終了によって情報が失われるのを避ける必要があります。