このページはコミュニティによって翻訳されたもので、最新ではない可能性があります。参照用のバージョンをご覧ください。
このページはコミュニティによって翻訳されたもので、最新ではない可能性があります。参照用のバージョンをご覧ください。
このページはコミュニティによって翻訳されたもので、最新ではない可能性があります。参照用のバージョンをご覧ください。
拡張ワーカーは、FrankenPHP拡張機能がバックグラウンドタスクの実行、非同期イベントの処理、またはカスタムプロトコルの実装のために、PHPスレッドの専用プールを管理できるようにします。キューシステム、イベントリスナー、スケジューラーなどに役立ちます。
ワーカーをユーザーが構成可能にする必要がない場合(固定スクリプトパス、固定スレッド数)、init() 関数でワーカーを登録するだけです。
package myextension
import (
"github.com/dunglas/frankenphp"
"github.com/dunglas/frankenphp/caddy"
)
// ワーカープールと通信するためのグローバルハンドル
var worker frankenphp.Workers
func init() {
// モジュールがロードされたときにワーカーを登録します。
worker = caddy.RegisterWorkers(
"my-internal-worker", // ユニークな名前
"worker.php", // スクリプトパス(実行場所からの相対パス、または絶対パス)
2, // 固定スレッド数
// オプションのライフサイクルフック
frankenphp.WithWorkerOnServerStartup(func() {
// グローバルなセットアップロジック...
}),
)
}
拡張機能を共有する予定がある場合(一般的なキューやイベントリスナーなど)、Caddyモジュールにラップする必要があります。これにより、ユーザーは Caddyfile を介してスクリプトパスとスレッド数を構成できます(例を見る)。
Caddyなしで標準GoアプリケーションにFrankenPHPを組み込む場合、初期化オプションで frankenphp.WithExtensionWorkers を使用して拡張ワーカーを登録できます。
ワーカープールがアクティブになったら、タスクをディスパッチできます。これは、PHPにエクスポートされたネイティブ関数内、またはGoのロジック(cronスケジューラー、イベントリスナー(MQTT、Kafka)、その他のゴルーチンなど)から実行できます。
SendMessageSendMessage を使用して、生データをワーカーのスクリプトに直接渡します。これはキューや単純なコマンドに最適です。
// #include <Zend/zend_types.h>
import "C"
import (
"context"
"unsafe"
"github.com/dunglas/frankenphp"
)
//export_php:function my_queue_push(mixed $data): bool
func my_queue_push(data *C.zval) bool {
// 1. ワーカーが準備できていることを確認する
if worker == nil {
return false
}
// 2. バックグラウンドワーカーにディスパッチする
_, err := worker.SendMessage(
context.Background(), // 標準のGoコンテキスト
unsafe.Pointer(data), // ワーカーに渡すデータ
nil, // オプションのhttp.ResponseWriter
)
return err == nil
}
SendRequest拡張機能が標準のウェブ環境($_SERVER、$_GET など)を期待するPHPスクリプトを呼び出す必要がある場合は、SendRequest を使用します。
// #include <Zend/zend_types.h>
import "C"
import (
"net/http"
"net/http/httptest"
"unsafe"
"github.com/dunglas/frankenphp"
)
//export_php:function my_worker_http_request(string $path): string
func my_worker_http_request(path *C.zend_string) unsafe.Pointer {
// 1. リクエストとレコーダーを準備する
url := frankenphp.GoString(unsafe.Pointer(path))
req, _ := http.NewRequest("GET", url, http.NoBody)
rr := httptest.NewRecorder()
// 2. ワーカーにディスパッチする
if err := worker.SendRequest(rr, req); err != nil {
return nil
}
// 3. キャプチャされたレスポンスを返す
return frankenphp.PHPString(rr.Body.String(), false)
}
PHPワーカーのスクリプトはループで実行され、生メッセージとHTTPリクエストの両方を処理できます。
<?php
// 同じループで生のメッセージとHTTPリクエストの両方を処理する
$handler = function ($payload = null) {
// ケース1: メッセージモード
if ($payload !== null) {
return "Received payload: " . $payload;
}
// ケース2: HTTPモード(標準のPHPスーパーグローバルが設定される)
echo "Hello from page: " . $_SERVER['REQUEST_URI'];
};
while (frankenphp_handle_request($handler)) {
gc_collect_cycles();
}
FrankenPHPは、ライフサイクルの特定の時点でGoコードを実行するためのフックを提供します。
| フックタイプ | オプション名 | シグネチャ | コンテキストと使用例 |
|---|---|---|---|
| サーバー | WithWorkerOnServerStartup | func() | グローバルなセットアップ。一度だけ実行されます。例: NATS/Redisへの接続。 |
| サーバー | WithWorkerOnServerShutdown | func() | グローバルなクリーンアップ。一度だけ実行されます。例: 共有接続のクローズ。 |
| スレッド | WithWorkerOnReady | func(threadID int) | スレッドごとのセットアップ。スレッドが開始したときに呼び出されます。スレッドIDを受け取ります。 |
| スレッド | WithWorkerOnShutdown | func(threadID int) | スレッドごとのクリーンアップ。スレッドIDを受け取ります。 |
package myextension
import (
"fmt"
"github.com/dunglas/frankenphp"
frankenphpCaddy "github.com/dunglas/frankenphp/caddy"
)
func init() {
workerHandle = frankenphpCaddy.RegisterWorkers(
"my-worker", "worker.php", 2,
// サーバー起動時 (グローバル)
frankenphp.WithWorkerOnServerStartup(func() {
fmt.Println("Extension: Server starting up...")
}),
// スレッド準備完了時 (スレッドごと)
// 注: この関数はスレッドIDを表す整数を受け入れます
frankenphp.WithWorkerOnReady(func(id int) {
fmt.Printf("Extension: Worker thread #%d is ready.\n", id)
}),
)
}