$30 off During Our Annual Pro Sale. View Details »

RoadRunnerの世界 〜 Yet Another Alt PHP-FPM

RoadRunnerの世界 〜 Yet Another Alt PHP-FPM

2021/05/29(土)PHPカンファレンス沖縄2021の登壇資料です

n1215
PRO

May 29, 2021
Tweet

More Decks by n1215

Other Decks in Programming

Transcript

  1. for PHPカンファレンス沖縄2021
    RoadRunnerの世界

         ~ Yet Another Alt PHP-FPM
    2021年5月29日 (土) 株式会社Nextat 中榮健二
    Nextat Inc. 1

    View Slide

  2. 自己紹介
    from 京都
    - 中榮健二 (なかえけんじ)
    - twitter: @n_1215 
    - 株式会社Nextat 取締役
    - Laravel中心にECサイトやシステム開発
    - 最近はFaaS+TSを使ったりUnityを使ったりPHP以外の仕事も増加
    Nextat Inc. 2

    View Slide

  3. 発表概要
    1. Alt PHP-FPMとは
    2. RoadRunnerとは
    3. RoadRunnerの設計思想
    4. Get Started with RoadRunner
    5. フレームワーク インテグレーション
    6. 利用上のハマりどころ
    7. まとめ
    Nextat Inc. 3

    View Slide

  4. 1. Alt PHP-FPMとは
    Nextat Inc. 4

    View Slide

  5. 1-1. 従来のPHP製Webアプリケーションの実行方式
       
    PHP-FPM (FastCGI Process Manager)
    NginxなどのWebサーバと併用
    Apache HTTP Server
    mod_php、mod_cgi etc.
    PHP-FPMとの併用も可
    Nextat Inc. 5

    View Slide

  6. 従来のPHP製

    Webアプリケーション
    1つのHTTPリクエストごとに
    状態をリセット
    毎回初期化処理を実行する
    Nextat Inc. 6

    View Slide

  7. 1-2. 従来のPHPのトレードオフ
    メリット
    メモリリークを気にしなくて良い
    HTTPリクエストをまたぐ状態を気にしなくて良い
    デメリット
    毎回初期化するオーバーヘッド
    とはいえ大抵の場合に充分なパフォーマンスは出せる
    OPCache、Preloading、JIT
    HTTPサーバを別途用意する必要がある
    PHPだけでHTTP Serverにはなれない
    WebSocket Server、gRPC Serverなど長時間実行が必要な用途に向かない
    Nextat Inc. 7

    View Slide

  8. 1-3. Alt PHP-FPM
    従来のPHPとは異なる実行方式を持つ新興のHTTP・アプリケーションサーバを

    本資料では
    Alt PHP-FPM
    と呼称
    Swoole
    ReactPHP
    Amp
    PHP-PM (PHP Process Manager)
    ※ ApacheやLighttpdやIISのことも忘れてませんが、一旦置いておいてください
    Nextat Inc. 8

    View Slide

  9. Swoole
    https://www.swoole.co.uk/
    コルーチンベースの非同期並行実行ライブラリ(PHP拡張/C言語)
    PHPのコードでHTTPサーバやWebSocketサーバを実装することが可能
    Coroutine、Fiber API
    中華圏での採用実績
    対応フレームワーク多数
    Nextat Inc. 9

    View Slide

  10. ReactPHP
    https://reactphp.org/
    PHPのイベント駆動プログラミングのライブラリ
    HTTPサーバやWebSocketサーバが実装可能
    EventLoop、Promise、Stream
    イベントループはNode.jsと同じReactorパターンを利用
    Nextat Inc. 10

    View Slide

  11. PHP-PM (PHP Process Manager)
    https://github.com/php-pm/php-pm
    PHPアプリケーションのプロセスマネージャ、ロードバランサ
    ベースにReactPHPを利用
    子プロセスでPHPをWorkerとして動かす
    Symfony/Laravelなどに対応
    Nextat Inc. 11

    View Slide

  12. Amp
    https://amphp.org/
    イベント駆動な並行処理のフレームワーク
    Event Loop、Promise、Coroutine、Stream
    PHPのコードでHTTPサーバを実装可能。HTTP/2対応
    Streaming対応gRPCサーバも実装できそう(過去の発表でお世話になった)
    Nextat Inc. 12

    View Slide

  13. HTTPサーバの例 (React)
    https://reactphp.org/
    $loop = React\EventLoop\Factory::create();

    $server = new React\Http\Server(

    $loop,

    function (Psr\Http\Message\ServerRequestInterface $request) {

    return new React\Http\Message\Response(

    200,

    ['Content-Type' => 'text/plain'],

    "Hello World!\n"

    );

    }

    );

    $socket = new React\Socket\Server(8080, $loop);

    $server->listen($socket);

    $loop->run();

    Nextat Inc. 13

    View Slide

  14. 毎回の初期化処理を省略できる
    Nextat Inc. 14

    View Slide

  15. 2. RoadRunner
    https://roadrunner.dev/
    Nextat Inc. 15

    View Slide

  16. Nextat Inc. 16

    View Slide

  17. RoadRunner
       
    https://roadrunner.dev/
    2018年リリース
    Golang製のPHPアプリケーションサーバ
    開発元は Spiral Scout 、開発者は Anton Titov 氏
    Nextat Inc. 17

    View Slide

  18. 前面のGoサーバがリクエストを受け付け、PHPのWorkerに振る構成
     

    https://roadrunner.dev/docs/intro-about より
    Nextat Inc. 18

    View Slide

  19. 特徴
    ワンバイナリでクロスプラットフォームで動く
    HTTPサーバ(HTTP/2対応、静的ファイル配信可)
    gRPCサーバ(今の所PHPで書けるのはUnary RPCのみ)
    FastCGIにも対応
    PHP拡張なしで利用できる
    Goによるカスタマイズが可能
    PHPからGoのサービスへのRPCが可能
    PHPのWorkerはPSR-7に標準対応
    プラグインで機能拡張可能
    Nextat Inc. 19

    View Slide

  20. パフォーマンス


    https://roadrunner.dev/features より
    注1: RoadRunnerが目立つが、NGINX Unitの性能も凄いのでは
    注2: Swooleが入っていないがSwooleのほうが速いだろうとのこと
    参考: https://youtu.be/mj6d-IGzSYE?t=2335
    Nextat Inc. 20

    View Slide

  21. 3. RoadRunnerの設計思想
    従来の実行方式との違いと他のAlt PHP-FPMとの比較
    Nextat Inc. 21

    View Slide

  22. ブログ記事: PHP is meant to die (2013/04)


    https://software-gunslinger.tumblr.com/post/47131406821/php-is-meant-to-
    die
    Nextat Inc. 22

    View Slide

  23. Software Gunslinger - PHP is meant to die
    著者はPHP4の頃から10年以上の経験を持つPHP開発者
    PHPという言語が滅ぶべくして滅ぶ、という話ではない
    PHPは実行がすぐ終わる(= die)ことを前提に設計されている
    合わない使い方はするなよ、という話
    WebSocketやキューワーカーのためにバックグラウンドでのコード実行したい
    だが、PHPをデーモン化する(Summon the daemons)とメモリリークな
    ど問題発生
    Python + Flask + Supervisor + Gunicornの構成に感銘を受けたらしい
    Nextat Inc. 23

    View Slide

  24. Software Gunslinger - PHP is meant to die, continued
    前記事の補足記事
    (現時点では)継続的に実行させるプロセスにPHPは向いていない、という主旨
    ReactPHPの検証
    メモリーリークの問題、安定性の問題
    ReactをWorkerで実行する方法なら望みはあるかも、という事も書いてある
    Nextat Inc. 24

    View Slide

  25. Can a long-living php application be
    pragmatic?
    Nextat Inc. 25

    View Slide

  26. RoadRunnerの開発者
    https://github.com/wolfy-j
    Anton Titov 氏 (a.k.a Wolfy-J)
    Spiral Scout CTO・共同創業者。Twitter @lachezis
    日本語Tweetにも「それRoadRunnerで出来るよ」とリプをくれるナイスガイ
    RoadRunnerに関するツイートは全て補足されている模様
    本資料の大半は氏の発表資料、動画を参考にしています
    Nextat Inc. 26

    View Slide

  27. PHPアプリケーションの高速化という課題
    初期化を前倒ししたい
    ライフサイクルの長いPHPスクリプトの実行が必要
    Nextat Inc. 27

    View Slide

  28. 既存のAlt PHP-FPMの比較と考察
    RoadRunner (スライド・ロシア語)
    https://docs.google.com/presentation/d/1YnymGamkustDeujhTJhyTN
    h9_UtayV7quzF-4H3W0tU
    PHPKonf 2020 - Anton Titov: Designing hybrid Go/PHP applications using
    RoadRunner(動画・英語)
    https://www.youtube.com/watch?v=mj6d-IGzSYE
    Nextat Inc. 28

    View Slide

  29. 既存の有力な選択肢のアプローチは二種類
    ノンブロッキング
    シングルプロセスで多重リクエストを処理
    メモリ消費量の低減
    コンテキストスイッチによるオーバーヘッドなし
    Reactorパターン
    コールバック地獄になるが、Promiseなどで解消
    既存のPHPのノンブロッキングではないライブラリとの相性が良くない
    ex) Node.js、EventMachine(Ruby)、Twisted(Python)
    Nextat Inc. 29

    View Slide

  30. ブロッキング
    マルチプロセス
    既存のライブラリ、SPLを普通に使える
    メモリリークの可能性
    コンテキストスイッチやプロセス間通信のコスト
    Nextat Inc. 30

    View Slide

  31. 既存の選択肢
    ReactPHP
    ノンブロッキング
    Promise
    すぐに使える、大規模コミュニティ、PHPで書かれている
    サーバとアプリケーションが同じPHPのプロセス
    Nextat Inc. 31

    View Slide

  32. Swoole
    ノンブロッキング
    2系からコルーチン
    コルーチン、超高速、大規模コミュニティ(中華圏)
    サーバとアプリケーションが同じPHPのプロセス、Windows非対応
    Nextat Inc. 32

    View Slide

  33. Amp
    ノンブロッキング
    Promise, コルーチン

    すぐに使える、PHPで書かれている

    サーバとアプリケーションが同じPHPのプロセス
    Nextat Inc. 33

    View Slide

  34. PHP PM
    ブロッキング
    マルチプロセス

    すぐに使える、コミュニティ、サーバとアプリケーションが別プロセス

    遅い、メモリリーク、Windows非対応
    Nextat Inc. 34

    View Slide

  35. 既存の選択肢では求める条件に合わなかった
    サーバ自体のプロセスはPHPではないほうが良い
    既存のライブラリやFWをそのまま使いたい
    どこでも動く
    ハイパフォーマンス
    Nextat Inc. 35

    View Slide

  36. 新しいアプリケーションサーバを作る
    目標
    既存の数あるFWとの互換性
    サーバプロセスとPHP Workerが別プロセス
    ハイパフォーマンス、安定性、エラーハンドリング
    PHPをビルディングブロックとして使うためのHTTPサーバ以上のなにか
    どこでも動く
    アーキテクチャを最小のオーバヘッドで用意に拡張
    Nextat Inc. 36

    View Slide

  37. サーバプロセスの選択
    Golang
    Spiral Scoutは2016年頃Golangを開発スタックに導入した
    高速なアプリケーションが設計可能であると実感
    軽量な並行処理の道具立て
    goroutine: ユーザ空間で動く軽量スレッド
    channel: マルチスレッドだが直接のメモリアクセスを行わないことを推奨
    Nextat Inc. 37

    View Slide

  38. PHPとのGoのプロセス間通信の選択肢
    既存のもの
    素晴らしいライブラリ deuill/go-php がすでにあったが合わなかった
    PHPのカスタムビルドが必要。設定が難しい
    共有メモリ
    OS依存
    ポテンシャルは高いが扱いが難しい
    ソケット/パイプを介したバイナリストリームによる通信
    古典的で実績のあるアプローチ
    こちらを採用
    Nextat Inc. 38

    View Slide

  39. Goridge
    https://github.com/spiral/goridge
    Pipe、UNIX/TCP Socketで動作
    小さいオーバーヘッド
    PHP側に追加の拡張は不要
    副産物として、PHPからRPCでGoのサービスを呼び出すことが可能になった
    Nextat Inc. 39

    View Slide

  40. Goridgeの実装に利用されたパッケージ
    Golang
    バイナリの扱い: encoding/binary
    標準入出力: io
    UNIX, TCP: net
    PHP
    バイナリの扱い: pack(), unpack()
    標準入出力: 組込みのストリーム
    Unix, TCP: 組込みのソケット
    Nextat Inc. 40

    View Slide

  41. HTTPスタック
    Goの
    net/http
    のHTTPリクエストをPHPに渡す際に
    PSR-7
    のリクエストに変換
    プロセスマネージャ、ロードバランサ
    時間の都合で割愛
    詳細は前述のPHPKonf 2020の動画を参照
    Nextat Inc. 41

    View Slide

  42. ブログ記事: PHP was never meant to die
    https://spiralscout.com/blog/php-was-never-meant-to-die
    PHP is meant to die
    に 対するアンサーを意識した題名
    従来のPHPの課題と非効率性
    既存のAlt PHP-FPMの選択肢への不満
    RoadRunnerの設計の概要
    負荷がスパイクする環境のNginx、PHP-FPMをRoadRunnerに置換
    502エラーを解消し、サーバを3分の2に減らせた
    Nextat Inc. 42

    View Slide

  43. 4. Get Started with RoadRunner
    Nextat Inc. 43

    View Slide

  44. インストール
    $ composer require spiral/roadrunner:v2.0 nyholm/psr7

    $ ./vendor/bin/rr get-binary

    $ chmod 744 rr

    現在の最新版は 2.2.1
    requires PHP >= 7.4
    PSR-7の実装パッケージが必要(ここでは nyholm/psr7)
    1系ではLaminas(Zend) Diactorosに依存していたが取り除かれた
    Composerでインストールし、コマンドを使ってバイナリをDL
    ※ DL時にサンプルの設定ファイルを生成するかどうか尋ねられるがNoで良い
    Nextat Inc. 44

    View Slide

  45. 設定ファイル .rr.yaml
    rpc:

    listen: tcp://127.0.0.1:6001

    server:

    command: "php worker.php"

    http:

    address: "0.0.0.0:8080"

    pool:

    num_workers: 4

    https://roadrunner.dev/docs/intro-config の 最小構成を参照
    Nextat Inc. 45

    View Slide

  46. PHP Worker のエントリポイント worker.php

    use Spiral\RoadRunner;

    use Nyholm\Psr7;

    include "vendor/autoload.php";

    $worker = RoadRunner\Worker::create();

    $psrFactory = new Psr7\Factory\Psr17Factory();

    $worker = new RoadRunner\Http\PSR7Worker($worker, $psrFactory, $psrFactory, $psrFactory);

    while ($req = $worker->waitRequest()) {

    try {

    $rsp = new Psr7\Response();

    $rsp->getBody()->write('Hello world!');

    $worker->respond($rsp);

    } catch (\Throwable $e) {

    $worker->getWorker()->error((string)$e);

    }

    }

    Nextat Inc. 46

    View Slide

  47. サーバを起動
    ディレクトリ構成

    起動コマンド
    $ ./rr serve

    http://localhost:8080 にアクセスするとHello, world! が表示される
    Nextat Inc. 47

    View Slide

  48. おまけ: Docker環境
    Spiral ScoutのRoadRunnerのDockerイメージ
    https://hub.docker.com/r/spiralscout/roadrunner
    ローカル開発用のDocker環境スケルトン (手前味噌ですが)
    https://github.com/n1215/roadrunner-docker-skeleton
    Docker ComposeとBashが必要
    $ git clone https://github.com/n1215/roadrunner-docker-skeleton.git your_app

    $ cd your_app

    $ ./task init

    $ ./task up

    Nextat Inc. 48

    View Slide

  49. 5. フレームワーク インテグレーション
    Nextat Inc. 49

    View Slide

  50. 多くのFWに対応 (サードパーティ多め)
    CakePHP https://github.com/CakeDC/cakephp-roadrunner
    Laminas Mezzio https://github.com/bcremer/roadrunner-mezzio-
    integration
    Laravel https://github.com/spiral/roadrunner-laravel
    Slim https://github.com/tanakahisateru/rr-slim
    Symfony https://github.com/baldinof/roadrunner-bundle
    Symlex https://github.com/symlex/symlex
    Yii https://forum.yiiframework.com/t/using-roadrunner-as-a-
    server/127060
    PSR-7を使っているものだと接続が簡単
    Symfony HTTP Foundation系列はPSR-7ブリッジを併用
    Nextat Inc. 50

    View Slide

  51. Laravel Octane
    https://github.com/laravel/octane
    Laravel公式のパッケージ
    高性能なアプリケーションサーバでパフォーマンスを向上
    Swoole または RoadRunner
    この機会にRoadRunnerも流行って欲しい
    今現在はSwoole限定の機能が多い?
    Swoole Tables を使ったキャッシュなど
    Nextat Inc. 51

    View Slide

  52. Spiral Framework
    https://spiral.dev/
    Spiral Scout謹製。RoadRunner前提のFW
    ControllerやHTTP層の処理自体は他のFWとほぼ変わらず
    注目すべきコンポーネント(独断)
    Cycle ORM: DoctrineライクなORM
    ジョブキュー: 開発用にはRoadRunner単体で利用できる
    WebSocket
    Temporal 連携: ワークフローエンジン
    Nextat Inc. 52

    View Slide

  53. Goで書けるならGoで拡張していこうというスタイル
    重いHTTP MiddlewareをGo側に移す
    JWTの検証
    Goのライブラリを使って書いたサービスをPHPからRPCで使う
    Goridgeの恩恵
    Goで書いた場合はRoadRunnerの自前ビルドが必要になる
    Nextat Inc. 53

    View Slide

  54. 6. 利用上のハマりどころ
    Nextat Inc. 54

    View Slide

  55. (1) メモリリーク
    RoadRunnerは利用メモリが多くなったWorkerを入れ替える設定も可能
    だが、当然メモリリークがないほうが良い
    注意してコードを書くと共に、信頼できるFWやライブラリを使うことも重要
    (2) グローバルな状態の汚染
    global、static変数の変更が共有される
    Worker間での状態の共有はないが、Worker内ではリクエストをまたぐ
    ログインユーザやセッションがリクエストをまたいで共有される恐怖
    DI・サービスコンテナの中身、シングルトン
    HTTPリクエストやHTTPリクエストから導出されるものはコンテナに保持し
    ないのが簡単
    もしくはリクエスト毎のスコープでオブジェクトを保持できるようにする
    Nextat Inc. 55

    View Slide

  56. (3) リソースのロック
    開いたリソースをすぐ閉じるのが基本
    DBコネクションを監視
    リクエストをまたぐファイルロックを避ける
    その他の注意事項はドキュメントを参照
    Caveats
    Production Usage
    他のAlt PHP-FPMに比べると少なめな印象
    Nextat Inc. 56

    View Slide

  57. 7. まとめ
    Nextat Inc. 57

    View Slide

  58. まとめ
    Alt PHP-FPMはPHPアプリケーションサーバの新潮流
    初期化の前倒しによってパフォーマンスの向上が見込める
    PHPの長時間実行により、WebSocketやgRPCサーバの実装も可能
    PHP-FPMからの移行先としてRoadRunnerは優しい選択肢の一つ
    PHP-FPM向けに比較的近い感覚でコードを書くことができる
    普段のPHP開発よりグローバルな状態やメモリリークへの配慮が必要
    同じ開発元のSpiral Frameworkを始め、フレームワークとの統合も進む
    用途があえばぜひ利用してみてください
    Nextat Inc. 58

    View Slide

  59. 蛇足
    gRPCサーバの改善を予定しているようです。期待
    ※ 現状PHPだけで書けるのはUnary RPCのみ
    たまに出てくるロシア語はGoogle翻訳などを使って読もう
    記号にしか見えない (゚Д゚)
    英語のほうが素直に変換される
    Nextat Inc. 59

    View Slide

  60. 参考資料
    RuadRunner公式サイト
    https://roadrunner.dev
    RoadRunner (スライド・ロシア語)
    https://docs.google.com/presentation/d/1YnymGamkustDeujhTJhyTN
    h9_UtayV7quzF-4H3W0tU
    PHP fwdays 2019 - Anton Tsitou "Designing hybrid Go/PHP applications
    using RoadRunner"(スライド・ロシア語)
    https://www.slideshare.net/fwdays/anton-tsitou-designing-hybrid-
    gophp-applications-using-roadrunner
    PHPKonf 2020 - Anton Titov: Designing hybrid Go/PHP applications using
    RoadRunner(動画・英語)
    https://www.youtube.com/watch?v=mj6d-IGzSYE
    Nextat Inc. 60

    View Slide

  61. PR: 開発者を募集しています
    株式会社Nextat nextat.co.jp
    受託開発
    業務システム、ECサイト、スマホアプリ...
    本社は京都ですが、東京・名古屋などリモートワーク実績あり
    設計の話に付き合ってくれる方大歓迎!
    Nextat Inc. 61

    View Slide

  62. アピールポイント
    RoadRunnerのサイトに弊社の記事のリンク
    Nextat Inc. 62

    View Slide

  63. ご清聴ありがとうございました
    Nextat Inc. 63

    View Slide