遅延処理
時には、遅延処理を行う必要があります。遅延処理がwebmanの他のリクエスト処理に影響を与えないようにするため、状況に応じて異なる処理方式を使用することができます。
方法1 メッセージキューを使用
利点
突発的な膨大なビジネス処理リクエストに対応できます。
欠点
結果をクライアントに直接返すことができません。結果をプッシュする必要がある場合は、他のサービスと組み合わせて使用する必要があります。たとえば、webman/pushを使用して処理結果をプッシュします。
方法2 HTTPポートを追加
HTTPポートを追加して遅延リクエストを処理します。この遅延リクエストは、このポートにアクセスすることで特定のプロセスのグループに入ります。処理後、結果を直接クライアントに返します。
利点
データをクライアントに直接返すことができます。
欠点
突発的な膨大なリクエストに対応できません。
実施手順
config/process.php
に次の設定を追加します。
return [
// ... ここでは他の設定を省略しています ...
'task' => [
'handler' => \Webman\App::class,
'listen' => 'http://0.0.0.0:8686',
'count' => 8, // プロセス数
'user' => '',
'group' => '',
'reusePort' => true,
'constructor' => [
'requestClass' => \support\Request::class, // requestクラスの設定
'logger' => \support\Log::channel('default'), // ログインスタンス
'appPath' => app_path(), // appディレクトリの位置
'publicPath' => public_path() // publicディレクトリの位置
]
]
];
これにより、遅延インターフェースは http://127.0.0.1:8686/
このグループのプロセスを通過し、他のプロセスのビジネス処理に影響を与えません。
フロントエンドがポートの違いを感じないようにするために、nginxに8686ポートへのプロキシを追加できます。遅延インターフェースのリクエストパスがすべて/tast
で始まると仮定すると、全体のnginx設定は次のようになります。
upstream webman {
server 127.0.0.1:8787;
keepalive 10240;
}
# 新しい8686アップストリームを追加
upstream task {
server 127.0.0.1:8686;
keepalive 10240;
}
server {
server_name webman.com;
listen 80;
access_log off;
root /path/webman/public;
# /tastで始まるリクエストは8686ポートを通過します。実際の状況に応じて/tastを必要なプレフィックスに変更してください
location /tast {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://task;
}
# 他のリクエストは元の8787ポートを通過します
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Connection "";
if (!-f $request_filename){
proxy_pass http://webman;
}
}
}
これにより、クライアントがdomain.com/tast/xxx
にアクセスすると、独自の8686ポートで処理され、8787ポートのリクエスト処理に影響を与えません。
方法3 http chunkedを利用してデータを非同期に分割送信
利点
データをクライアントに直接返すことができます。
workerman/http-clientをインストール
composer require workerman/http-client
app/controller/IndexController.php
<?php
namespace app\controller;
use support\Request;
use support\Response;
use Workerman\Protocols\Http\Chunk;
class IndexController
{
public function index(Request $request)
{
$connection = $request->connection;
$http = new \Workerman\Http\Client();
$http->get('https://example.com/', function ($response) use ($connection) {
$connection->send(new Chunk($response->getBody()));
$connection->send(new Chunk('')); // 空のchunkを送信してresponseを終了させる
});
// 先にhttpヘッダーを送信し、その後のデータを非同期で送信する
return response()->withHeaders([
"Transfer-Encoding" => "chunked",
]);
}
}
ヒント
この例では、workerman/http-client
クライアントを使用してhttp結果を非同期に取得しデータを返していますが、他の非同期クライアント(例えばAsyncTcpConnection)を使用することもできます。