🏃

PHP アプリケーションサーバー RoadRunner

2023/04/13に公開

はじめに

ポートでPHPエンジニアをしている @sawada です。
今回は、PHPのアプリケーションサーバー の RoadRunner について調査しました。
ご参考になれば幸いです。

RoadRunner とは

RoadRunner は、go で作成された php のアプリケーションサーバーで、
Spiral Scount というサンフランシスコにある、受託開発企業によって作成されました。

go と php を組み合わせることで、既存の php アプリケーションに様々な可能性を見せてくれます。

主な特徴としては、以下の点が挙げられます。

  • 大幅なパフォーマンス向上が見込める
  • 既存の php アプリケーションにも比較的簡単に導入できる
  • プラグインの導入により、機能の拡張が可能
  • grpc, websocket サーバーなどの構築も可能

RoadRunner の処理の流れを見ていくと共に、これらの特徴についても解説していきたいと思います。

処理の流れ


https://spiral.dev/docs/http-lifecycle/3.6/en より参照

処理の流れは、以下の通りです。

1. go でクライアントからのリクエストを受ける

  • go の http ハンドラを使用して処理されます。

2. リクエストが go 側で psr(psr-15) の形式へ変換される

  • psr-15 は、リクエストに関する規格となります。

3. 変換されたリクエスト(psr-15)はソケット通信を行い、php の worker プロセスへ転送される

  • サーバー起動時に go routine によって生成された php の worker プロセスに対してリクエストを振り分けます。
  • go -> php 間のやり取りは、goridgeというライブラリが利用されています。

4. php worker でアプリケーションのコードが実行され、psr(psr-7) の形式で返される

  • psr-7 は、レスポンスに関する規格となります。

5. レスポンス(psr-7)が go 側へ転送され、クライアントへレスポンスが返される。

  • php -> go 間のやり取りは、goridge-php というライブラリが利用されています。

次は、特徴について見ていきます。

特徴

大幅なパフォーマンス向上が見込める

従来の php アプリケーション(php-fpm など)では、リクエスト毎にアプリケーションの初期化(フレームワークのファイルの読み込みやクラスの定義など)が走っており、それにより大量のメモリが使用されていました。

RoadRunner では、アプリケーションの初期化はサーバー起動時の1度のみとなります。
処理の流れでも説明したように、リクエストは go で処理され、初期化済みの php プロセスへ転送される事となります。
これにより大幅なパフォーマンス向上が見込めます。

既存の php アプリケーションにも比較的簡単に導入できる

既存の多くのフレームワークでは、リクエスト・レスポンス に psr を使用しているので、導入も簡単です。
laravel では、laravel octane,
cakephp では、cakephp-roadrunner
などを利用することも可能です。

また、現状 psr を使用していないようなアプリケーション(素の php で記述されたものなど)であっても、以下の様にリクエスト・レスポンスを psr の形式へ変換するだけで導入が可能となります。

index.php
<?php
// ...
$data = [
    'hello' => 'world',
    'foo' => [
        'bar', 'bar', 'bar'
    ],
];

echo json_encode($data);

index.php
<?php
// ...

return new Psr7\Response(200, [
  'Content-Type' => 'application/json'
], json_encode(data));

※psr のレスポンスを返すように変更し、include './index.php'とするようなイメージ

プラグインの導入により、機能の拡張が可能

RoadRunner は、 endure を利用することで、プラグインの導入を可能にしています。

go 側で、何かしらの処理を行いたい、処理を完結させたい場合はこちらを利用することで様々な実装が可能となります。

現在、公式から提供されている主だった機能としては、以下のものが挙げれれます。

  • ジョブ(キューイングシステム)
  • log の記述
  • static ファイルの提供
  • key-value ストアの利用
    詳細は、こちらをご覧下さい。

また、endure から提供されているインターフェース と velox(独自のプラグインを導入してRoadRunner をビルドするためのツール) を使用することで、独自のプラグインを組み込んだ RoadRunner をビルドすることも可能となっております。
https://github.com/roadrunner-server/endure#endure-main-interface
https://roadrunner.dev/docs/app-server-build/2.x/en


実際に使ってみた

今回は、アプリケーションの実装は割愛し、主に RoadRunner の設定周りを解説します。
今回の実装は、github に公開しているので、気になったらご覧下さい。
https://github.com/Sawawada8/rr-example

環境構築

docker を使用して開発環境を構築します。

https://github.com/Sawawada8/rr-example/blob/33ed67fb3ef4c5ef73bee70fcaad5b21078c65e0/docker/php/Dockerfile#L1-L18

解説

  • go, php 間でのソケット通信の為に php の socket 拡張をインストールします。(line: 9)
  • RoadRunner の docker image が提供されているのでそちらから rr(RoadRunner のバイナリ) をコピーします。(line: 18)

設定ファイルの記述

.rr.yaml にサーバーの設定やプラグインの設定を記述します。

https://github.com/Sawawada8/rr-example/blob/b95407591e67ba0285551af44341704495a30089/.rr.yaml#L1-L39

解説

  • staticファイルを提供するプラグイン(http middleware)を有効化しています。(line: 10)
    • 今回は、htmlcss を静的ファイルとして公開します。
  • logger プラグインを有効化しています。(line: 21~)
  • reload プラグインを有効化しています。(line: 31~)
    • こちらを有効化することで、ホットリロードが有効になります。
    • また、xdebug も従来通り利用できるようになります。

workerの実装

https://github.com/Sawawada8/rr-example/blob/b95407591e67ba0285551af44341704495a30089/worker.php#L1-L38

解説

  • 今回実装では、App\Router::dispatch(line: 33) で、controller のメソッドが呼ばれ、最終的に Psr7\Response のオブジェクトが返されるようになっています。

サーバーの起動

rr serve

まとめ

php アプリケーションサーバー RoadRunnerについて調査しました。
個人的に非常に魅力を感じているプロジェクトなので、今後も調査を続け、記事にしていきたいと思います!

また、RoadRunner に興味を持った方は是非、開発元 Spiral Scout のブログ記事も読んでみて下さい!php に対する熱い思いが綴られている非常に素晴らしい記事となっております!

今回は、以上となります。ご精読ありがとうございました。

参考

https://roadrunner.dev/docs
https://spiral.dev/docs/http-lifecycle/3.6/en
https://spiralscout.com/blog/php-was-never-meant-to-die

Discussion