140 Views
November 06, 25
スライド概要
に頼らずに でリアルタイム 通信を実現する Node.js FrankenPHP Web 1
目次 1. リアルタイム通信をPHPで行う難しさ 2. FrankenPHPで実現するリアルタイム通信 3. Mercure Hubの役割 4. FrankenPHPの構成から得られるメリット 5. WebSocketを視野に入れるタイミング 6. まとめ 2
リアルタイム通信を PHPで行う難しさ 3
リアルタイム通信とは? クライアントが更新操作をしなくても通知を受け取れる サーバーとクライアントが即座に情報をやり取りする技術 様々なアプリケーションで活用されている チャットアプリ、ライブ配信、コメント機能 ダッシュボードの通知機能etc... 4
リアルタイム通知の要望 ダッシュボードのステータス変更を通知させたい 在庫情報をリアルタイムに通知させたい etc...b こんな要望が上がってきた場合 PHPアプリケーションでどう対応するか 5
のリアルタイム通信対応時の課題 📌 前提 PHP PHPは1リクエスト完結型で常時接続が前提ではない PHP-FPM/Apacheで接続を長時間維持する =PHPプロセスが常時起動し、プロセス数が枯渇しやすい エコシステムの不足 PHPでやろうとすると、イベントループやノンブロッキングI/Oを自前でまかなう必 要がある 6
従来の対応方法の選択肢 「別の仕組みを足す/リアルタイム性を下げる」の3パターン 🧩 別の仕組みを足す 1. 常時接続は別レイヤーで持つ 2. 外部サービスに肩代わりさせる ⏳ リアルタイム性を下げる 3. ポーリングで疑似的にリアルタイム通信 7
従来の対応方法パターン1,2 🧩 別の仕組みを足す 1. 常時接続は別レイヤーで持つ Node.js などリアルタイム通信用のランタイムを追加導入 PHPはAPI役に徹して、リアルタイム通信用のNode.js2台構成で対応するパターン 2. 外部サービスに肩代わりさせる Pusher 等のPush SaaSやサーバレス基盤へ通知処理を委譲 PHPはトリガーのみ担当 8
従来の対応方法パターン1,2 イメージ図 9
従来の対応方法パターン3 ⏳ リアルタイム性を下げる 3. ポーリングで疑似的にリアルタイム通信 リアルタイム性を下げて、クライアント側から定期的 にサーバーへ問い合わせる(例:5秒毎にサーバー通信など) PHP単体で実装可能 10
従来の対応方法に伴う課題 「別の仕組みを足す/リアルタイム性を下げる」 いずれも運用を続けていく中で課題が残る 1. 常時接続は別レイヤーで持つ ⚠️ 課題 Node.jsなど別途サーバーを保守する必要性 PHP1台と比べて、監視やCI/CDの管理も2倍になる 2. 外部サービスに肩代わりさせる ⚠️ 課題 Pusher等のPush SaaSへ委譲すると 従量課金額や、データガバナンスの制約 3. ポーリングで疑似的にリアルタイム通信 ⚠️ 課題 定期的なリクエストが発生するため リクエストが単純増加し、UXもリアルタイム感に欠ける 11
FrankenPHP で解決する ⚠️ 課題: Node.jsなど別途サーバーを保守する必要性 PHP1台と比べて、監視やCI/CDの管理も2倍になる ✅ 解決: FrankenPHPがSSE(Server Sent Events)を内包しているため、監視や デプロイはPHP基盤に統一可能 ⚠️ 課題: Pusher等のPush SaaSへ委譲すると 従量課金額や、データガバナンスの制約 ✅ 解決: FrankenPHPサーバーのみで閉じ、他への依存無し ⚠️ 課題: 定期的なリクエストが発生するため リクエストが単純増加し、UXもリアルタイム感に欠ける ✅ 解決: 常時接続で即時配信可能 ポーリングより少ないトラフィックでUXも改善 12
デモ紹介 実際にFrankenPHPで作成した2つのリアルタイムWeb通信を使ったデモを紹介し ます 1. ダッシュボードのリアルタイム通知 2. 購入者数のリアルタイム同期 13
1.ダッシュボードのリアルタイム通知 送信したメッセージが即受信される 14
2.購入者数のリアルタイム同期 左と右で、購入者の数がリアルタイムで同期されている 15
FrankenPHPを使うと こういったリアルタイム通信が 実現可能になります!! 16
この後の流れ 以下の点を紹介・解説していきます どのような仕組みでリアルタイム通信を成立させたのか 既存の技術要素との比較紹介 その仕組みを採用することで得られる具体的なメリット 実サービスへの適用ポイント・注意点 本編の前に軽く自己紹介をさせてください 17
自己紹介 発表者 所属 ma@me 最近の業務 不具合分析 不具合対応 品質改善業務をメインに色々やっ てます 18
直近の登壇 PHP実行環境の歴史 - PHP-FPMからFrankenPHPの誕生へ https://www.docswell.com/s/1313108/ZP2QQ1-2025-03-21-123847 どこまで違う?!PHP実行環境パフォーマンス対決 - mod_php vs php-fpm vs Swoole vs FrankenPHP https://www.docswell.com/s/1313108/ZGGREJ-2025-07-17-000927 19
採用情報 バックエンドエンジニア絶賛募集中 https://booost-tech.notion.site/3a148cd671c845ecb2778a19bc592829 20
で実現する リアルタイム通信 FrankenPHP 21
デモの振り返り こんな感じのリアルタイム通信が FrankenPHPだけで実装できる 22
実現に必要なもの この機能の実現に必要な準備はこれだけです ⚙️ バックエンド側 1. ライブラリ(Symfony Mercure Hubコンポーネント)の インストールと実装 2. URLに対応するコントローラークラスの実装 🌐 フロントエンド側 1. イベントの購読処理の実装 23
リアルタイム通信はどこが担うのか? FrankenPHPに内包されているMercure Hubが リアルタイム通信に必要な基盤を整えてくれています 24
Mercure Hub の役割 25
Mercure (メルキュール)とは? サーバーからクライアントへのリアルタイム通信を可能にする オープンプロトコル Server-Sent Events を基盤にしていて、様々なクライアントに対して、サーバーか らのプッシュ通知を簡単に実装可能 特徴 サーバーからクライアントへの一方向のデータフローに特化 標準的なHTTP/2上で動作するため、既存のWebインフラと親和性が高い WebSocketに比べてクライアント側の実装も容易。 26
Mercure Hub (メルキュールハブ)とは? Mercureプロトコルの中心的な役割を担うサーバー クライアントからのイベントを待ち受け、購読しているクライアントにイベントを 配信する 特徴 イベントの配信: トピックに送信された更新を、トピックを購読しているすべての クライアントにリアルタイムで配信 認証と認可: JWTでイベントを購読できるように制御可能 FrankenPHPへの統合: FrankenPHPにはMercure Hubが組み込まれており、追加の 設定なしでリアルタイム通信機能を利用可能 27
FrankenPHP 込みで見た全体像 28
Mercure Hub とPHPの通信 概要図 Mercure Hubが公開しているアクセスポイント .well-known/mercure ここにアクセスすると、イベント発行の依頼が届く 29
Mercure Hub
とPHPの通信 コードイメージ
$hub = new \Symfony\Component\Mercure\Hub(
'https://localhost/.well-known/mercure', $provider
);
$updateID = $hub->publish(
new \Symfony\Component\Mercure\Update('my-topic', […])
);
30
Mercure からブラウザへ Mercure Hubが直接ブラウザへイベントを送信する PHPはメッセージの送信をお願いすれば それ以降はMercure Hubにお任せなので PHPはプロセスの負荷を気にせずに済む 31
Mercure
からのSSEを購読する
const source = new EventSource(`${hubUrl}`, {・・・});
eventSource.onopen = () => updateStatus('open');
eventSource.addEventListener('mercure-demo', appendEvent);
eventSource.onmessage = appendEvent;
クライアント側はJSネイティブのEventSourceで購読可能
追加ライブラリ不要でシンプルに実装に
32
全体像振り返り 必要なものはほとんどFrankenPHPに含まれている 33
構成要素の紹介という名の宣伝 今回紹介を省くPHPプロセス部分や Caddyなどの内包アプリケーション(下記リスト1, 2) については下記発表資料で説明しています(宣伝) 1. Webサーバー:Caddy 2. PHPランタイム:PHP 8.3+ 3. Mercure Hub:リアルタイム通信のためのミドルウェア PHP実行環境の歴史 PHP-FPMからFrankenPHPの誕生へ どこまで違う?!PHP実行環境パフォーマンス対決 - mod_php vs php-fpm vs Swoole vs FrankenPHP 34
FrankenPHP るメリット の構成から得られ 35
この構成のメリット3点 WebサーバーやPHPランタイム、 Mercure Hubが統合されていることで得られる 主なメリットは以下の通り 1. サーバー構成が簡素化される 2. 依存関係が閉じている 3. プロセスが分離している 36
メリット1:サーバー構成が簡素化される 💻💻 PHP + Nodejs 2台構成 リアルタイム通信用に NodeJS+WebSocketのサーバーを立てた場合 監視・デプロイ・アップデート諸々を各サーバーに対応が必要 管理コストが2倍 37
メリット1:サーバー構成が簡素化される 💻 FrankenPHP 1台構成 全部含まれているので、監視・メンテ・デプロイ・アップデートなどが1台で済む いろんなコストが1/2に 38
メリット2:依存関係が閉じている 🔗 外部サービスへの依存があるケース 外部にデータを送るので、データガバナンスの制約が発生する 外部サービスとの通信コストが高い 39
メリット2:依存関係が閉じている 🔗 外部サービスへの依存がない、FrankenPHP すべて自身で閉じるので、データガバナンスの制約は発生しない 自身の中でのやりとりなので通信コストが低い 40
メリット3:プロセスが分離している 🔄 ポーリング運用のケース クライアントからの定期的なサーバーへのリクエストが多数発生し、 PHPプロセスを消費するため、PHPのMaxプロセス数に達しやすくなる 41
メリット3:プロセスが分離している 🔄 FrankenPHPのプロセス運用 PHPプロセスと分離されているため、PHPのMaxプロセス数には影響が無い 42
FrankenPHP のメリットのまとめ PHP資産をそのまま活かして リアルタイム通信基盤を構築可能! サーバー構成が簡素 メンテナンスが楽! 43
とはいえ FrankenPHPですべてのリアルタイム通信要件を満たせるのか? Nodejs + WebSocketとの違いは?どっちがいいの? ここを説明していきます 44
を視野に 入れるタイミング WebSocket 45
SSE とWebSocketの違い FrankenPHPで実現されるリアルタイム通信は 「SSE(Server-Sent Events) 」単方向通信 WebSocket との違いを知って、使い分けを考えましょう ↔️ SSEとWebSocketの違い 1. SSEとWebSocketの違い 2. 活用しやすいアプリケーション例 46
とWebSocketの違い SSE ➡️ 単方向通信:SSE(Server-Sent Events) SSE FrankenPHPが内蔵しているMercureが採用している リアルタイム通信技術 サーバーからブラウザへの 一方通行のイベント配送 クライアントは「受信」と「描画」の2つに集中する 47
とWebSocketの違い WebSocket 🔁 双方向通信:WebSocket SSE クライアントとサーバーが常時やり取りする 双方向通信 Nodejs は WebSocket 環境を構築するうえで相性が良い クライアントは「受信」と「送信」と「描画」の3つを担う 48
活用しやすいアプリケーション例 SSE SSEが向いているのは「一方的な通知」で済むケース 例 在庫更新を常時配信する監視ダッシュボード タスク状況の進捗状況を伝えるアラート ECやメールの送信状況を即座に知らせる通知フィード 49
活用しやすいアプリケーション例 WebSocket WebSocketが向ているのは「リアルタイムな双方向のやり取り」が必要なケース 例 ユーザー同士の入力を同期するチャットやコラボエディタ 即応性が求められるリアルタイムゲームや投票アプリ 入力結果を双方向で共有するカスタマーサポートUI 50
向き・不向きまとめ SSE・FrankenPHPは手段であって、目的ではない 双方向性や複雑なリアルタイム制御が要求される場合は WebSocketと相性のいいNodeJSを検討する 向かないケースで無理に使っても メリットがデメリットに変わってしまうので要注意 51
まとめ 52
まとめ FrankenPHPのメリット FrankenPHPとMercure Hubを組み合わせることで、PHP単体でリアルタイムWeb 通信(SSE)を実現可能 Node.jsなどの追加サーバーが不要になり、運用コストを削減し、PHP資産を最大 限に活用できる サーバー構成を簡素化し、依存関係を閉じ、プロセス分離によるPHPプロセスの負 荷軽減を実現 53
まとめ 技術選択と運用のポイント SSEはサーバーからクライアントへの単方向通信に優れており、監視ダッシュボー ドや通知機能に最適 双方向通信や複雑なリアルタイム制御が必要な場合はWebSocketの利用を検討し、 要件に応じた技術選択が重要 適切なイベント設計を整えることで、持続可能なリアルタイム通信運用が可能で す。 要件に合わせた技術を組み合わせ、適切なコストで最適なリアルタイム体験を届け ましょう。 54
今日の資料リンク先 資料やコードは下記リンクから参照できます。 SSEやFrankenPHPが気になった方は是非試してみてください。 今日の発表が、皆さんのプロジェクトの助けになれば幸いです。 ご清聴ありがとうございました。 https://github.com/gmagmeg/php-push-event-sample 55