【初期化クラスの実装】
はじめに
初期化クラスは、サーバー起動時に必要なデータ(UNITパラメータインスタンス)や処理(ログライター、シリアライザー/アンシリアライザー、コマンドディスパッチャー、緊急停止コールバック)を読み込むための実装を行うところで、専用のコマンドを使ってスキャルフォールディングできます。
初期化クラスを生成するコマンドは以下の通り。
コマンドを実行する事で
以降では生成されたクラス内で実装が必要なインターフェイスメソッドの内訳を見ていきます。
初期化クラスを生成するコマンドは以下の通り。
> php worker craft:init InitForTest [success] 初期化クラスの生成に成功しました (InitForTest)
コマンドを実行する事で
app/InitClass
の場所にInitForTest
というクラス名でIInitSocketManager
インターフェイスをimplementsした初期化クラスが生成されます。以降では生成されたクラス内で実装が必要なインターフェイスメソッドの内訳を見ていきます。
➤ログライター
error_logの標準関数やLoggerなどの有名なライブラリを使ってログを出力する事ができます。
イベントハンドラ(UNIT)内ではパラメータ経由で使いますので
※カレントパスはプロジェクトルートになるので
※このメソッドはフレームワークのライブラリからもコールされますので、イベントハンドラのログも含めて時系列で出力されます。
イベントハンドラ(UNIT)内ではパラメータ経由で使いますので
$param->logWriter('debug', ['メッセージ受信' => $message])
のように記述します。【メソッド】getLogWriter(): Closure|string|null 【パラメータ】なし 【戻り値】 Closure|string|null - ログ出力を行う場合: Closure パラメータ: $p_level - string - 必須 - ログレベル 現状では以下のレベルが定義されています。 debug info notice warning error $p_param - array - 必須 - 出力内容 連想配列の形式で以下のように指定します。 ['メッセージ受信' => $message] 戻り値: void - ログ出力を行う場合: string ヘルパー関数などの関数名 - ログ出力を行わない場合: null
public function getLogWriter() { return function(string $p_level, array $p_param) { // ファイル名を設定 $filename = date('Ymd'); // 現在日付を含むログ内容を作成 $now = date('Y-m-d H:i:s'); $log = $now." {$p_level} ".print_r($p_param, true)."\n"; // ログ出力(カレントパスはプロジェクトルートになる) error_log($log, 3, "./logs/socket-manager-log/{$filename}.log"); }; }
※カレントパスはプロジェクトルートになるので
./logs/debug.log
のように指定します。※このメソッドはフレームワークのライブラリからもコールされますので、イベントハンドラのログも含めて時系列で出力されます。
➤シリアライザー
送信するデータをシリアライズするためのメソッドを実装します。
※シリアライザーはデータ送信時にライブラリから自動でコールされます。
※Websocketサーバーとして使う場合はJSON形式で使うのがいいでしょう。
※通信データ量を減らすためにバイナリデータを扱う事も可能です。
【メソッド】getSerializer(): Closure|string|null 【パラメータ】なし 【戻り値】 Closure|string|null - シリアライズを行う場合: Closure パラメータ: $p_data - mixed - 必須 - 送信データ イベントハンドラで設定された送信データがそのまま渡されます。 戻り値: mixed シリアライズ後のデータ - シリアライズを行う場合: string ヘルパー関数などの関数名 - シリアライズを行わない場合: null
public function getSerializer() { return function($p_data) { return json_encode($p_data); }; }
※シリアライザーはデータ送信時にライブラリから自動でコールされます。
※Websocketサーバーとして使う場合はJSON形式で使うのがいいでしょう。
※通信データ量を減らすためにバイナリデータを扱う事も可能です。
➤アンシリアライザー
受信データを取得する時にアンシリアライズするためのメソッドを実装します。
※アンシリアライザーは受信データ取得時にライブラリから自動でコールされます。
※Websocketサーバーとして使う場合はJSON形式で使うのがいいでしょう。
※通信データ量を減らすためにバイナリデータを扱う事も可能です。
【メソッド】getUnserializer(): Closure|string|null 【パラメータ】なし 【戻り値】 Closure|string|null - アンシリアライズを行う場合: Closure パラメータ: $p_data - mixed - 必須 - 受信データ シリアライズされている受信データがそのまま渡されます。 戻り値: mixed アンシリアライズ後のデータ - アンシリアライズを行う場合: string ヘルパー関数などの関数名 - アンシリアライズを行わない場合: null
public function getUnserializer() { return function($p_data) { return json_decode($p_data, true); }; }
※アンシリアライザーは受信データ取得時にライブラリから自動でコールされます。
※Websocketサーバーとして使う場合はJSON形式で使うのがいいでしょう。
※通信データ量を減らすためにバイナリデータを扱う事も可能です。
➤コマンドディスパッチャー
受信データを受け取った時に呼び出され、そのデータを解析した上でサーバーコンテンツ(コマンドUNIT)上の適切なイベントハンドラを呼び出すためのルーティングの役割を果たします。
コマンドディスパッチャーからは、ルーティングするキュー名を返す事でイベントハンドラを呼び出す事ができます。
コマンドディスパッチャーからは、ルーティングするキュー名を返す事でイベントハンドラを呼び出す事ができます。
【メソッド】getCommandDispatcher(): Closure|string|null 【パラメータ】なし 【戻り値】 Closure|string|null - コマンドディスパッチャーを使う場合: Closure パラメータ: $p_param - SocketManagerParameter - 必須 - UNITパラメータクラスのインスタンス 各イベントハンドラで共通の引数として使用されるインスタンス。 SocketManagerParameterクラスを継承した拡張クラスを指定する事も可能。 $p_dat - mixed - 必須 - 受信データ アンシリアライズ化された受信データがそのまま渡されます。 戻り値: string ルーティングするキュー名 - コマンドディスパッチャーを使う場合: string ヘルパー関数などの関数名 - コマンドディスパッチャーを使わない場合: null
public function getCommandDispatcher() { return function(SocketManagerParameter $p_param, $p_dat): ?string { // コマンド部のキュー名と一致している必要があります return $p_dat['command']; }; }
➤緊急切断コールバック
クライアントとの接続が維持できなくなった時に呼び出されるコールバックメソッドを実装します。
例えば以下の場面で呼び出されます。
例えば以下の場面で呼び出されます。
- アライブチェック処理のタイムアウト
- コマンドディスパッチャーでの例外発生
- 相手先による強制切断
【メソッド】getEmergencyCallback(): Closure|string|null 【パラメータ】なし 【戻り値】 Closure|string|null - 緊急切断コールバックを使う場合: Closure パラメータ: $p_param - SocketManagerParameter - 必須 - UNITパラメータクラスのインスタンス 各イベントハンドラで共通の引数として使用されるインスタンス。 SocketManagerParameterクラスを継承した拡張クラスを指定する事も可能。 戻り値: mixed シリアライズ後のデータ - 緊急切断コールバックを使う場合: string ヘルパー関数などの関数名 - 緊急切断コールバックを使わない場合: null
public function getEmergencyCallback() { return function(SocketManagerParameter $p_param) { // 送信データを作成 $send_data = []; $send_data['command'] = 'close'; $send_data['message'] = '切断されました'; $send_data['connection_id'] = $p_param->getConnectionId(); // 接続IDを取得 // 全員へ配信(第二パラメータがtrueの場合は自身を除く) $p_param->setSendStackAll($send_data, true); }; }
➤UNITパラメータインスタンス
UNITとしてのイベントハンドラを実行する時に渡されるUNITパラメータクラスのインスタンスを指定します。
基底クラスである
ここで指定したインスタンスはそのままUNITの引数として使われますので、動的に増殖してメモリを圧迫する心配はありません。
※UNITパラメータクラスの詳細については▶UNITパラメータクラスのページをご覧ください。
基底クラスである
SocketManagerParameter
クラスのインスタンスがデフォルトで指定されていますが、このクラスを継承した拡張クラスを使用する場合はそのインスタンスを戻り値に指定する必要があります。ここで指定したインスタンスはそのままUNITの引数として使われますので、動的に増殖してメモリを圧迫する心配はありません。
【メソッド】getUnitParameter(): SocketManagerParameter|null 【パラメータ】なし 【戻り値】SocketManagerParameter|null - UNITパラメータクラスを使う場合: SocketManagerParameter 各イベントハンドラで共通の引数として使用されるインスタンス。 SocketManagerParameterクラスを継承した拡張クラスを指定する事も可能。 - UNITパラメータクラスを使わない場合: null
public function getUnitParameter(): ?SocketManagerParameter { return new SocketManagerParameter(); }
※UNITパラメータクラスの詳細については▶UNITパラメータクラスのページをご覧ください。
おわりに
生成されたクラスのインスタンスは、メイン処理クラス内で
複数の初期化クラスやメイン処理クラスを用意している場合は、サーバーの実装内容によって最適なインスタンスを動的、あるいは静的に適用する事で柔軟なサーバー構築が可能になります。
$manager->setInitSocketManager()
メソッドに引き渡す事で適用されます。複数の初期化クラスやメイン処理クラスを用意している場合は、サーバーの実装内容によって最適なインスタンスを動的、あるいは静的に適用する事で柔軟なサーバー構築が可能になります。