概要
- RustでPHPサーバーを作った(実験)
- libphp, PHP-FPM, 静的ファイル配信をリクエストごとに動的に切り替える(既存の単一バイナリソリューションにはない実装)
- Nginx + PHP-FPMの1.8〜2.1倍のパフォーマンス
- 実運用性の証明として67,000リクエスト処理でエラー0%、メモリ使用量22MB
- TUIモニター内蔵でリアルタイム監視をSSH経由でも監視可能に
なぜ作ったのか
mod_phpだろうがphp-fpmだろうがnginx + リバースプロキシだろうがapacheだろうがPHPerは何も困っていない。
ログを追う面倒さ、そしてFirewallの設定なりパケットフィルタの設定はまた別になり、WAFは...と多岐にわたりすぎている問題から目を背ければね。
Claude Code on the Webが無料で$1000利用できる機会を活かすべく、小難しいことはAIに任させて動くもの作ってみるかぁと長き宿縁に終止符を打つべく作成した。
他と何が違うのか
1. 適材適所のハイブリッドアーキテクチャ
単一バイナリ製品はFrankenPHPなりSwooleなりRymfonyがあるけれどもアプローチが一つしかない。これにはPHPerは納得いかない。libphpでもphp-fpmでも資源は有効に使うべきだと思いハイブリッドバックエンドアーキテクチャとしてリクエストパスに応じてlibphpを直接実行するのかPHP-FPMにプロキシするのか直接配信するのかを単一バイナリにやらせている部分が唯一無二であります。
2. TUI Monitor内蔵
ターミナルでリアルタイムに監視を行え、SSH経由でリモート監視も可能なTUIビルドイン機能。
こんなん

リモート監視する場合は踏み台経由するなりして
ssh production-server "fe-php monitor --socket /var/run/fe-php-admin.sock"
ここが結構気に入っています。
Nginxのログ見るとかApacheのログ、PHP-FPMのログを見るなど忙しいですからね。
ログの自動解析つけてあるので、問題となりそうである部分を素早く察知できます。
3. API経由での完全統合
# 設定リロード
echo '{"command":"reload_config"}' | socat - UNIX-CONNECT:/var/run/fe-php-admin.sock
# IPブロック
echo '{"command":"block_ip","ip":"192.168.1.100"}' | socat - UNIX-CONNECT:/var/run/fe-php-admin.sock
# ステータス確認
curl http://localhost:9001/api/status | jq .
とても簡単です。
OSレベルでipfw add deny ip from 192.168.1.100 to any 80したり
ipfw listでルール確認して削除するなんて面倒から解放されます。
適材適所ってことでfail2banを利用するのも良いとは思うけれども、あっちこっちに設定書いてどこで制御しているのかをサーバー毎に各設定を読め!というのは...あまりにもつらい。
パフォーマンス
テスト環境: Apple M1 Max、32GB RAM、macOS Sequoia 15.1
| サーバー | 実測RPS | Nginx比 | p50レイテンシ | p99レイテンシ |
|---|---|---|---|---|
| Nginx + PHP-FPM | 209.86 | 1.0x | 4ms | 10ms |
| fe-php (Hybrid) | 374.80 | 1.79x | 2ms | 3ms |
| サーバー | 実測RPS | Nginx比 | p50レイテンシ | p99レイテンシ |
|---|---|---|---|---|
| Nginx + PHP-FPM | 201.18 | 1.0x | 4ms | 11ms |
| fe-php (Hybrid) | 429.76 | 2.14x | 1ms | 5ms |
FastCGIプロトコルのオーバーヘッドないのとプロセス間通信ないのでそれはそうなんですけど、早いは正義ってことで。
実運用...耐えられるのか?!
耐えられる。
上述の通りMacOSでの検証ですが、Embedded PHP + FastCGIをハイブリッド利用して4workerで以下のテストを行った。
1. 基本負荷テスト(100 RPS)
=== 結果 ===
実測RPS: 84.24 RPS
総リクエスト: 2,528
成功率: 100.00%
エラー: 0件
レスポンスタイム:
p50: 2ms
p75: 2ms
p95: 3ms
p99: 5ms
max: 18ms
安定
2. 中負荷テスト(500 RPS)
=== 結果 ===
実測RPS: 339.70 RPS
総リクエスト: 10,192
成功率: 100.00%
エラー: 0件
レスポンスタイム:
p50: 2ms
p75: 3ms
p95: 3ms
p99: 5ms
max: 22ms
安定
3. 高負荷テスト(1000 RPS)
=== 結果 ===
実測RPS: 307.48 RPS
総リクエスト: 9,225
成功率: 100.00%
エラー: 0件
レスポンスタイム:
p50: 3ms
p75: 3ms
p95: 4ms
p99: 7ms
max: 71ms
安定。とはいっても時間が短いので
4. 5分間安定性テスト
=== 結果 ===
実測RPS: 151.99 RPS
総リクエスト: 45,597
成功率: 100.00%
エラー: 0件
レスポンスタイム:
p50: 3ms
p75: 3ms
p95: 6ms
p99: 11ms
max: 94ms
問題なし。
5. メモリ使用量
$ ps aux | grep "fe-php serve"
USER PID %CPU %MEM VSZ RSS
ORE xxx 0.0 0.1 435MB 22MB
22MB
Nginx+PHP-FPMでは250MB程度必要としていたので中々削減されたのではないかと思う。
# Nginx
worker_processes: 4
worker_connections: 1024
keepalive: 65
# PHP-FPM
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
6. レスポンスの一貫性
10回連続でリクエストを送信したときのレスポンスタイム
2.990ms
2.585ms
2.609ms
2.495ms
3.431ms
2.477ms
2.404ms
2.821ms
3.042ms
2.449ms
平均: 2.73ms
標準偏差: 0.35ms
ということで、実運用性はあると言えます。
libphpと密結合なので気軽に実用は出来ないけどね。
設定ファイル1個で全部動く良さ
以下が内蔵されていることにより
- HTTPサーバー
- PHP実行環境
- 静的ファイル配信
- WAF
- レート制限
- メトリクス
- 管理API
- TUI Monitor
- TLS/SSL
- CORS
- グレースフルシャットダウン
設定ファイル一つメンテナンスすればいい良さがある。
[server]
host = "0.0.0.0"
port = 8080
workers = 4
[php]
libphp_path = "/usr/local/lib/libphp.so"
document_root = "/var/www/html"
[backend]
enable_hybrid = true
default_backend = "embedded"
[admin]
enable = true
unix_socket = "/var/run/fe-php-admin.sock"
http_port = 9001
[waf]
enable = true
mode = "block"
実際の使い方イメージ
Nginxでやっても同じようなもんなのですが、一元管理できるのが味噌です。
皆大好きWordPress
# 公開ページ → 高速なEmbedded
[[backend.routing_rules]]
pattern = { type = "prefix", value = "/" }
backend = "embedded"
priority = 50
# 管理画面 → 安定性重視のFastCGI
[[backend.routing_rules]]
pattern = { type = "prefix", value = "/wp-admin/" }
backend = "fastcgi"
priority = 100
# アップロード画像 → 直接配信
[[backend.routing_rules]]
pattern = { type = "prefix", value = "/wp-content/uploads/" }
backend = "static"
priority = 90
セキュリティ機能
WAF(Web Application Firewall)
[waf]
enable = true
mode = "block" # または "detect"
[waf.rate_limit]
requests_per_ip = 100
window_seconds = 60
burst = 20
- SQLインジェクション検出
- XSS検出
- パストラバーサル検出
- カスタムルール定義
- レート制限
- 動的IPブロック
- ログの自動解析
動的IPブロック
# IPブロック
echo '{"command":"block_ip","ip":"192.168.1.100"}' | socat - UNIX-CONNECT:/var/run/fe-php-admin.sock
# ブロック解除
echo '{"command":"unblock_ip","ip":"192.168.1.100"}' | socat - UNIX-CONNECT:/var/run/fe-php-admin.sock
ログ探しからの解放
- 従来
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log
tail -f /var/log/php-fpm/error.log
...
- fe-php
fe-php monitor
これだけ
ログ自動分析機能によって以下を素早く確認。
- エンドポイント別の統計
- 遅延リクエストの検出
- 不審なアクティビティ検出
実際にはもっと詳細に様々なログを追うことになりますが,素早くあたりを付けられることが大きいと思います。
まとめ
従来の問題
- 設定, ログの分散
- オーバーヘッド
- 監視が煩雑
fe-phpの解決策
- 単一バイナリ、単一設定
- TUI統合監視
- ハイブリッドバックエンド
