世界最速のPHPウェブサーバーを構築した
I built the fastest PHP webserver in the world (qbixserver.com)
要約
開発者は、Swoole、FrankenPHP、RoadRunnerといった既存のソリューションよりも高速であると主張する、純粋なPHPで書かれた新しいウェブサーバー「Qbix」を発表しました。このサーバーは、PHPのコードを一切変更せず、追加の拡張機能やDockerも不要で、単一のファイルまたはバイナリとして動作します。大量のワーカープロセスを効率的に管理するCopy-on-Write(COW)メモリ共有技術により、低メモリフットプリントで高いスループットを実現します。
全文翻訳
Qbix Server: 世界最速のPHPウェブサーバー
[画像]
1台のマシンで100倍のユーザーを処理
OSレベルのプロセス分離により、すべてのHTTPリクエストとWebSocketルームをデフォルトで安全に処理します。PHPの共有なしアーキテクチャに基づいたQbix Serverは、数千の既存PHPウェブサイト★を修正なしで実行できます。現在、Linux、Mac、Windows、iOS、Androidで動作し、署名および配布可能なスタンドアロンバイナリを生成できます。さらに、v2ではアプリを分散化し、Wi-FiとBluetooth経由でオフラインでも作業を継続することが容易になりました。🤯
★ WordPress、OwnCloud、Magento、Drupal、Joomla、およびQbix、Laravel、Symfonyなどのフレームワークが含まれます。
git clone https://github.com/Qbix/webserver
cd webserver
php qbixserver.php
または、自己完結型バイナリ(Linux、macOS、Windows)を入手してください
curl -LO https://github.com/Qbix/webserver/releases/latest/download/qbixserver-macos-arm64
chmod +x qbixserver-macos-arm64
./qbixserver-macos-arm64
すべてを1つのプロセスで
nginx + fpm + Node + Redis + supervisor + Dockerを置き換えます。
スループット14倍
ワーカーあたり120KBの永続ワーカー。200MBで400ワーカー。fpmが78のところ、1,060 req/s。
詳細はこちら →
WebSocket + ルーム
HTTPと同じポート。ルームは共有状態を持つフォークされたプロセスです。Socket.IOプロトコル。Node不要。
詳細はこちら →
未変更のPHP
WordPress、Laravel、Symfony、Drupal。27の関数がファイルロードとして書き換えられています。.htaccessを読み込みます。そのまま動作します。
詳細はこちら →
マイクロサービス分離
設定変更1つで権限とサンドボックス化。同じコード、異なる役割。シークレットは権限から漏れません。
詳細はこちら →
クラスターレプリケーション
SQLiteを使用した複数のサーバー。イベントがレプリケートされます。ノードを停止し、再起動すると、キャッチアップします。
詳細はこちら →
画像処理
?w=400でリサイズ。AcceptヘッダーからAVIFまたはWebPを提供。Save-Dataサポート。元の画像が変更されたときに再生成されるディスクキャッシュ。
詳細はこちら →
スマートレスポンスヘッダー
コンポーネントごとの無効化のためのX-Cache-Tree。アクセス制御されたファイルのためのX-Accel-Redirect。ETag生成。ディレクトリリスティング。
詳細はこちら →
自動生成APIドキュメント
ハンドラーファイルを記述すると、OpenAPI 3.1およびMCP仕様が自動的に生成されます。Swagger UI、Postman、Redoc — そしてAIツールがアプリのAPIに直接呼び出し可能になります。
詳細はこちら →
TLS、Cron、ロギング
証明書が存在する場合、HTTPSが自動的に開始されます。組み込みのcronスケジューラ。バッファリングされたアクセスログは、日次ローテーションとgzipアーカイブを備えています。
詳細はこちら →
さらに、チャット、カンバン、SSEストリーム、REST API、ライブカウンター、分散スウォームの6つのサンプルアプリが含まれています。例を見る →
v2.0の新機能
オフラインでも動作し続けるアプリ
すべてのQbix Serverは暗号学的IDを持ち、BluetoothおよびWi-Fi経由で近くの他のサーバーを見つけることができます。同じバスや同じ建物にいる、または信号のない場所にいる電話は、中央サーバーなしで、エンドツーエンドで暗号化され、直接データを交換できます。
//ピアの出現と消失に反応
Q_WebServer_Transport::onPeerOnline(function ($peer) {
Q_WebServer_MeshSync::syncWithPeer('notes', $peer['peer_id'], $since,
array('Q_WebServer_Transport', 'requestFromPeer'));
});
v1.xからの破壊的変更はありません。メッシュレイヤーはピアが検出されるまで何も行いません。リリースノート →
fpm(50ms I/O)比14倍
fpm(200ms I/O)比24倍
ワーカーあたり120KB(COW)
状態リセット0.03ms
💡 なぜ他のすべてよりも高速なのか
php-fpmの問題点: opcacheが有効かどうかにかかわらず、本番PHPコードの大部分はI/Oバウンドです。ワーカーはデータベース、ファイルシステム、API呼び出しを待ちます。その待ち時間中、ワーカーは何もしていませんが、30〜60MBのRAMを占有しています。4GBサーバーでは、fpmはせいぜい80ワーカーしか得られません。それぞれが200msのクエリでブロックされます。それが限界です。
Swoole、RoadRunner、FrankenPHPの問題点: これらはPHPをNode.jsのようにイベント駆動にすることで解決しようとします。しかし、それは彼らの非同期ライブラリを使用するようにコードを書き直すことを意味します。すべてのWordPressプラグインやLaravelパッケージのPDO::query()、file_get_contents()、curl_exec()はブロッキングI/Oを使用します。それは譲歩しません。Swooleは協力しないコードを助けることはできません。
Qbixの解決策: 各ワーカーにもっと多くのことをさせるのではなく、より多くのワーカーを実行します。サーバーはフレームワークを親プロセスにロードし、pcntl_fork()を呼び出します。カーネルはすべてのページをコピーオンライト(COW)としてマークします。各ワーカーは親のロードされたクラスを共有し、書き込んだページのみを負担します。WordPressのようなリクエストは30ページを汚染します = 120KB。fpmが80ワーカーを得るのと同じ4GBで、Qbixは数千のワーカーを得ます。
コードは2つのモードで変更なしで実行されます:
永続ワーカー(デフォルト) — ワーカーはリクエスト間で生存します。27の関数がファイルロードとして書き換えられています。静的プロパティは0.03msでスナップショットから復元されます。これは高速パスです:CPUバウンドな作業で2,294 req/s。
リクエストごとのフォーク — シムが追跡できないコード(内部静的変数を持つ関数、追跡不可能なグローバル状態を登録するプラグイン)用。各リクエストは新しいフォークを取得します。永続モードより遅いですが、各ワーカーのコストは依然として120KBであり、50MBではありません — そのため、同じハードウェアでfpmよりも100倍多くのワーカーを実行できます。それがすべてです。
Windowsでも — フォークが利用できない場合でも、サーバーは同じ27関数の書き換えで永続ワーカーを実行します。COWメモリの節約はありませんが、同じコード互換性と同じコントロールパネルが得られます。
私たちはこれをPHPコアに提案しました(switch_global_context()として)。それがRFCプロセスを経ていく間、サーバーは今日ユーザーランドでそれを実行します。
🔍 Swoole、FrankenPHP、php-fpmとのベンチマーク
CPUバウンド(WordPress風ワークロード、同じ200MB):
| ワーカー | req/s | fpm比 | |
|---|---|---|---|
| php-fpm | 4 | ~350 | — |
| Swoole | 4 | ~400 | 1.1倍 |
| Qbix | 100 | 2,294 | 6.6倍 |
I/Oバウンド(50msデータベースクエリ):
| ワーカー | req/s | fpm比 | |
|---|---|---|---|
| php-fpm | 4 | 78 | — |
| Swoole (コルーチン*) | 4 | ~300 | ~4倍 |
| Qbix | 100 | 1,060 | 14倍 |
I/Oバウンド(200ms — 実際のデータベース負荷):
| ワーカー | req/s | fpm比 | |
|---|---|---|---|
| php-fpm | 4 | 20 | — |
| Swoole (コルーチン*) | 4 | ~200–500 | ~10–25倍 |
| Qbix | 200 | 488 | 24倍 |
- Swooleコルーチンには
Runtime::enableCoroutine()とコルーチン対応ドライバーが必要です。未変更のWordPress/LaravelはブロッキングI/Oを使用し、fpmの限界に達します。
🛡️ 27の関数が書き換えられる — 状態がリセットされる仕組み
ワーカーは永続的で、再起動なしで数千のリクエストを処理します。各リクエスト間、Reflectionベースのスナップショットが0.03msで全静的プロパティを復元します。27のPHP関数は、PHPがコンパイルする前に、各ファイルがロードされるときに書き換えられます:
header(), setcookie(), session_start(), move_uploaded_file(), ini_set(), register_shutdown_function(), set_error_handler(), spl_autoload_register(), putenv(), およびその他の18関数 — これらはすべてリクエストごとに追跡され、リクエスト間にクリーンアップされます。
未変更のWordPress、Laravel、Symfony、Drupalは、共有なしの安全性を自動的に取得します。アダプター不要、コード監査不要。
完全な互換性詳細 → · 各フレームワークで書き換えられるもの →
📊 1台の月額30ドルのマシンでどれだけのユーザーを処理できるか?
| メトリック | php-fpm | Qbix |
|---|---|---|
| 4GBでのワーカー数 | ~80 (各50MB) | 400 (各120KB) |
| スループット (200ms I/O) | ~80 req/s | ~2,000 req/s |
| 同時アクティブユーザー | 1,600 | 40,000 |
| 登録アカウント | 16K–32K | 400K–800K |
| WebSocket | Node.jsが必要 | 100K+ 組み込み |
| データベース | Postgresが必要 | SQLite (50K書き込み/秒) |
| 月額コスト | $30 + DBサーバー | 合計 $30 |
1台のマシン。データベースサーバー、Redis、Node、Dockerなし。冗長性のためにDNSフェイルオーバーを備えた2台目を追加 — 分散モードは両方のSQLiteコピーを同期させ続けます。
事前ロード後のフォーク
すべてを一度ロードします。ワーカーをフォークします。各ワーカーは120KB、42MBではありません。
親プロセス (30MB)フレームワーク · ルート · キャッシュCOWCOWワーカー (120KB)ワーカー (120KB)ワーカー (120KB)ワーカー (120KB)php-fpm: 4 × 42MB = 168MBQbix: 400 × 120KB = 47MB同じコード。同じRAM。100倍のワーカー。
ライブダッシュボード
/Q/dashboardで組み込み。Grafana不要、Prometheus不要。
localhost:4000/Q/dashboard
Qbix Server Dashboard
2,847Req/min
142接続
400ワーカー
23msレイテンシ
99.8%稼働率
47MBメモリ
200 GET /api/users 12ms
200 POST /api/tasks 34ms
304 GET /css/app.css 1ms
200 WS /Q/ws upgrade 2ms
開始方法
git clone https://github.com/Qbix/webserver
cd webserver
php qbixserver.php --root=examples/todo/web
どこでも実行可能
お使いのプラットフォーム用のバイナリをダウンロードしてください。PHPは内部にバンドルされているため、インストールは不要です。
Linuxx86_64 & ARM64 · COWフォーク
macOSApple Silicon & Intel · COWフォーク
Windowsx64 · 永続ワーカー
iOS & Androidarm64 · メッシュトランスポート
LinuxとmacOSでは、約120KBのCOWフォークワーカーが数千。Windowsでは、同じ27関数の書き換えを備えた永続ワーカー。電話では、ネイティブBluetoothおよびWi-Fiトランスポートの背後にある同じサーバー。FreeBSDはソースからビルドします。
既存のコードベースで使用
nginx + php-fpmで実行中のPHPアプリがある場合、切り替えは1コマンドです。
cd my-laravel-app && php qbixserver.php --root=public --preset=laravel
cd my-wordpress-site && php qbixserver.php --root=. --preset=wordpress
cd my-symfony-app && php qbixserver.php --root=public --preset=symfony
cd my-drupal-site && php qbixserver.php --root=web --preset=drupal
まず永続モードを試してください — ほとんどのアプリに対応しています。フォークごとのリクエストが必要な場合でも、同じハードウェアでfpmよりも100倍多くのワーカーを実行できます。コードがどのように書き換えられるか →