Slide 1

Slide 1 text

for PHPカンファレンス沖縄2021 RoadRunnerの世界      ~ Yet Another Alt PHP-FPM 2021年5月29日 (土) 株式会社Nextat 中榮健二 Nextat Inc. 1

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

1-3. Alt PHP-FPM 従来のPHPとは異なる実行方式を持つ新興のHTTP・アプリケーションサーバを 本資料では Alt PHP-FPM と呼称 Swoole ReactPHP Amp PHP-PM (PHP Process Manager) ※ ApacheやLighttpdやIISのことも忘れてませんが、一旦置いておいてください Nextat Inc. 8

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

Nextat Inc. 16

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

前面のGoサーバがリクエストを受け付け、PHPのWorkerに振る構成   https://roadrunner.dev/docs/intro-about より Nextat Inc. 18

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

ブログ記事: PHP is meant to die (2013/04) https://software-gunslinger.tumblr.com/post/47131406821/php-is-meant-to- die Nextat Inc. 22

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

既存の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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

Amp ノンブロッキング Promise, コルーチン すぐに使える、PHPで書かれている サーバとアプリケーションが同じPHPのプロセス Nextat Inc. 33

Slide 34

Slide 34 text

PHP PM ブロッキング マルチプロセス すぐに使える、コミュニティ、サーバとアプリケーションが別プロセス 遅い、メモリリーク、Windows非対応 Nextat Inc. 34

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

ブログ記事: 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

Slide 43

Slide 43 text

4. Get Started with RoadRunner Nextat Inc. 43

Slide 44

Slide 44 text

インストール $ 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

Slide 45

Slide 45 text

設定ファイル .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

Slide 46

Slide 46 text

PHP Worker のエントリポイント worker.php 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

Slide 47

Slide 47 text

サーバを起動 ディレクトリ構成 起動コマンド $ ./rr serve http://localhost:8080 にアクセスするとHello, world! が表示される Nextat Inc. 47

Slide 48

Slide 48 text

おまけ: 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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

多くの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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

7. まとめ Nextat Inc. 57

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

参考資料 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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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