目次
2 つのプログラミング言語をマージする際に遭遇する問題
RoadRunner で開発スタックを改善できる方法
結論
ホームページ バックエンド開発 PHPチュートリアル スピードのために生まれた: PHP と Golang の組み合わせ - RoadRunner

スピードのために生まれた: PHP と Golang の組み合わせ - RoadRunner

Sep 23, 2022 pm 07:40 PM
php golang

スピードのために生まれた: PHP と Golang の組み合わせ - RoadRunner

過去 10 年間、当社は Fortune 500 企業 およびユーザー数 500 人以下の企業向けのアプリケーションを開発してきました。これまで、当社のエンジニアは主に PHP を使用してバックエンドを開発してきました。しかし 2 年前、当社製品のパフォーマンスだけでなくスケーラビリティにも深刻な影響を与えるいくつかの問題が発生しました。そこで、当社は Golang (Go) を当社のテクノロジー スタックに導入しました。

ほぼ同時に、Go を使用すると大規模なアプリケーションを作成できるだけでなく、パフォーマンスが最大 40 倍向上することもわかりました。これにより、PHP で書かれた既存の製品を拡張し、両方の言語の長所を組み合わせて改良することができます。

Go と PHP の豊富な経験を通じて、それを実際の開発上の問題を解決するために使用する方法、およびそれを PHP Death Model を排除するツールに変える方法を説明します。いくつかの質問。

一般的な PHP 開発環境

#Go が PHP デス モデルをどのように改善するかを説明する前に、まず一般的な PHP 開発環境について理解しましょう。

通常、アプリケーションは nginx と PHP-FPM で実行されます。 nginx は静的リクエストを処理しますが、動的リクエストは PHP コードを実行する PHP-FPM にリダイレクトされます。おそらく Apache と mod_php を使用していると思いますが、原理は同じで、動作方法にわずかな違いがあるだけです。

PHP-FPM がコードをどのように実行するかを見てください。リクエストを受信すると、PHP-FPM は PHP サブプロセスを初期化し、ステータス (_GET、_POST、_SERVER など) の一部としてリクエストの詳細を転送します。

PHP スクリプトの実行中に状態を変更することはできないため、新しい入力データのセットを取得する唯一の方法は、プロセス メモリをクリアして再度初期化することです。

このパフォーマンス モデルには多くの利点があります。メモリ消費についてあまり心配する必要はありません。すべてのプロセスは完全に分離されており、プロセスの 1 つが「停止」しても、自動的に再作成され、他のプロセスには影響しません。ただし、アプリケーションを拡張しようとする場合、このアプローチには欠点があります。

一般的な PHP 環境の欠点と非効率

PHP で専門的に開発している場合は、新しいプロジェクトを作成するときにどこから始めるべきか、つまり フレームワークの選択 を知っています。これは、依存関係注入、ORM、変換、およびテンプレート メソッドのライブラリです。もちろん、ユーザーが入力したすべてのデータは単一のオブジェクト (Symfony / HttpFoundation または PSR-7) に簡単に配置できます。これらのフレームは素晴らしいです!

しかし、何事にも代償はつきものです。どのようなエンタープライズ フレームワークでも、単純なユーザー リクエストを処理したりデータベースにアクセスしたりするには、少なくとも数十個のファイルをロードし、多くのクラスを作成し、複数の構成を解析する必要があります。しかし最悪なのは、各タスクが完了した後、すべてをリセットして再起動する必要があることです。開始したばかりのコードはすべて役に立たなくなり、その助けを借りて別のリクエストを処理できなくなります。これを他の言語で書いているプログラマーに伝えてみると、彼の顔が混乱しているのがわかるでしょう。

長年にわたり、PHP エンジニアは、遅延読み込み技術、マイクロフレーム、最適化ライブラリ、キャッシュなどを使用して、この問題を解決する方法を探してきました。しかし、最終的にはアプリケーション全体を放棄して最初からやり直す必要があります* (翻訳者注: PHP7.4 でのプリロードの登場により、この問題は部分的に解決されます)

PHP プロセスで処理できる処理複数のリクエスト?

Cron ジョブ、CSV パーサー、キュー ハンドラーなど、数分を超える (最大で数時間または数日) 持続する PHP スクリプトを作成できます。これらのジョブはすべて、タスクを取得して処理し、次のタスクを取得するというパターンに従います。コードはメモリ内に常駐するため、フレームワークやアプリケーションを読み込むための追加操作が回避され、貴重な時間を節約できます。

しかし、長時間実行されるスクリプトの開発はそれほど簡単ではありません。エラーが発生するとプロセスが強制終了され、メモリ オーバーフローが発生するとクラッシュが発生し、F5 キーを使用してプログラムをデバッグすることはできません。

PHP 7 以降、状況は改善されました。信頼できるガベージ コレクターが登場し、エラーの処理が容易になり、カーネルの拡張によりメモリ リークを回避できるようになりました。はい、エンジニアは依然としてメモリとコード内の状態を記憶する問題に注意深く対処する必要があります (これらのことに注意を払わずに済む言語は何でしょうか?) もちろん、PHP 7 では、驚くべきことはそれほど多くありません。

HTTP リクエストの処理など、より簡単なタスクに常駐 PHP スクリプトのモデルを採用して、リクエストごとにすべてを最初からダウンロードする必要をなくすことは可能でしょうか?

この問題を解決するには、まず、HTTP リクエストを受信し、毎回 PHP ワーカーを強制終了するのではなく、1 つずつリダイレクトできるサーバー アプリケーションを実装する必要があります。

Web サーバーは純粋な PHP (PHP-PM) または C 拡張機能 (Swoole) で作成できることがわかっています。それぞれのアプローチには利点がありますが、どちらのオプションも私たちにとってはうまくいきませんでした。私はもっと何かが欲しかったのです。私たちは単なる Web サーバー以上のものを必要としていました。PHP の「再起動」に関連する問題を回避しながら、特定のアプリケーションに簡単に適応および拡張できるソリューションを求めていました。つまり、アプリケーションサーバーが必要です。

Go はこの問題の解決に役立つでしょうか?この言語がアプリケーションを単一のバイナリにコンパイルすること、クロスプラットフォームであること、HTTP を処理するために独自の並列処理モデル (同時実行性) とライブラリを使用すること、そして最終的には、より多くのオープン ソース ライブラリをプログラム。

2 つのプログラミング言語をマージする際に遭遇する問題

まず、2 つ以上のアプリケーションが相互に通信する方法を決定する必要があります。

たとえば、Alex Palaestras の go-php ライブラリを使用すると、PHP と Go プロセス (Apache の mod_php など) の間でメモリ共有を実現できます。ただし、このライブラリの機能により、問題を解決するための使用が制限されます。

私たちは、ソケット/パイプラインを使用してプロセス間の対話を構造化するという、別のより一般的なアプローチを使用することにしました。このアプローチは過去 10 年間にわたってその信頼性が証明されており、オペレーティング システム レベルで適切に最適化されています。

まず、プロセス間でデータを交換し、送信エラーを処理するための単純なバイナリ プロトコルを作成しました。最も単純な形式では、このタイプのプロトコルは、固定サイズのパケット ヘッダー (この例では 17 バイト) を持つ netstring に似ています。ここで含まれる情報は、パケット タイプ、そのサイズ、およびバイナリ マスクです。データの整合性をチェックするために使用される情報。

PHP 側では

pack 関数 を使用し、Go 側では encoding/binary ライブラリを使用しました。

1 つのプロトコルは私たちにとって少し時代遅れになっており、

net /rpc Go サービス を PHP から直接呼び出す機能を追加しました。この機能は、Go ライブラリを PHP アプリケーションに簡単に統合できるため、後の開発で非常に役立ちました。この作業の結果は、当社の別のオープンソース製品 Goridge で見ることができます。

複数の PHP ワーカー間でタスクを分散する

対話メカニズムが実装された後、タスクを PHP プロセスに適切に転送する方法を検討し始めました。タスクが到着すると、アプリケーション サーバーはそれを実行するためにアイドル状態のワーカーを選択する必要があります。ワーカー プロセスがエラーで終了するか、「終了」した場合は、ワーカー プロセスをクリアして新しいプロセスを作成します。ワーカー プロセスが正常に実行されると、ワーカー プロセスがワーカー プールに返され、そこでタスクの実行に使用できるようになります。

スピードのために生まれた: PHP と Golang の組み合わせ - RoadRunner

アクティブなワーカー プロセス プールを保存するために、

バッファ チャネル を使用します。予期しない「デッド」ワーカー プロセスをプールに、エラーとワーカー プロセスのステータスを追跡するメカニズムを追加しました。

ついに、バイナリ形式でレンダリングされたあらゆるリクエストを処理できる、動作する PHP サーバーが完成しました。

アプリケーションが Web サーバーとして動作できるようにするには、受信 HTTP リクエストを処理するための信頼できる PHP 標準を選択する必要があります。この例では、単純な net/http リクエストを Go

から PSR-7 形式に変換するだけで、現在利用可能な PHP フレームワークのほとんどと互換性があります。

PSR-7 は不変であると考えられているため (技術的に不変であるという人もいます)、開発者は原則としてリクエストをグローバル エンティティとして扱わないアプリケーションを作成する必要があります。これは、PHP 常駐プロセスの概念と完全に一致しています。最終的な実装 (まだ名前は付けられていません) は次のようになります:

スピードのために生まれた: PHP と Golang の組み合わせ - RoadRunner

RoadRunner - - パフォーマンス PHP アプリケーション サーバー

最初のテスト タスクは、定期的に (通常より頻繁に) 予測できないリクエストのバーストが発生する API バックエンドです。ほとんどの場合、nginx の機能で十分ですが、予想される負荷の増加に応じてシステムのバランスを迅速にとることができないため、502 エラーが発生することがよくあります。

この問題を解決するために、2018 年初めに最初の PHP/Go アプリケーション サーバーをデプロイしました。そしてすぐに驚くべき結果を達成しました! 502 エラーを完全に排除しただけでなく、サーバーの数を 3 分の 2 に減らし、大量のコストを節約し、エンジニアやプロダクト マネージャーの悩みを解決しました。

今年の半ばに、私たちはソリューションを改良し、#RoadRunner という名前で MIT ライセンスの下で GitHub 上でリリースし、その驚くべきスピードと効率性を強調しました。

RoadRunner で開発スタックを改善できる方法

RoadRunner を使用すると、Go 側でもミドルウェア net/http を使用できるようになります。リクエストが PHP に送信される前の JWT 検証、および Prometheus での WebSocket とグローバル集約状態の処理。

組み込み RPC のおかげで、拡張パッケージを作成しなくても、PHP で Go ライブラリの API を開くことができます。さらに、RoadRunner を使用すると、HTTP とは異なる新しいサーバーを展開できます。例には、PHP での AWS Lambda プロセッサの実行、強力なキュー セレクター、 の作成、さらにはアプリケーションへの gRPC の追加などが含まれます。

PHP と Go の両方を使用することで、ソリューションは着実に改善され、一部のテストではアプリケーションのパフォーマンスが 40 倍向上し、デバッグ ツールが改善され、Symfony フレームワークとの統合が可能になり、HTTPS、HTTP/2、プラグインのサポートが追加されました。そしてPSR-17。

結論

一部の人々は依然として PHP の時代遅れの概念に縛られており、PHP は遅くて扱いにくい言語であり、WordPress でプラグインを作成する場合にのみ適していると考えています。これらの人々は、PHP には限界があるとまで言います。アプリケーションが十分に大きくなると、より「成熟した」言語を選択し、長年にわたって蓄積されたコード ベースを書き直さなければなりません。

これらの質問に対する私の答えは、「もう一度考えてください」です。 PHP に制限を設けているのはあなただけだと思います。自分のニーズに完全に一致する言語を見つけようとして、ある言語から別の言語に人生を移すこともできますし、言語をツールとして扱うこともできます。 PHP のような言語では、その想定される欠陥が成功の本当の理由である可能性があります。 Go などの別の言語と組み合わせると、1 つの言語を使用するよりも強力な製品を作成できます。

Go と PHP を同じ意味で使用した後、私たちはそれらが好きだと言えます。私たちは一方を犠牲にして他方を犠牲にするつもりはありません。代わりに、この二重アーキテクチャからより多くを引き出す方法を見つけるつもりです。

英語の元のアドレス: https://sudonull.com/post/6470-RoadRunner-PHP-is-not-created-to-die-or-Golang-to-the-rescue

翻訳アドレス: https://learnku.com/php/t/61733

推奨学習: 「PHP ビデオ チュートリアル

以上がスピードのために生まれた: PHP と Golang の組み合わせ - RoadRunnerの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 Apr 05, 2025 am 12:04 AM

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

PHPでの後期静的結合を説明します(静的::)。 PHPでの後期静的結合を説明します(静的::)。 Apr 03, 2025 am 12:04 AM

静的結合(静的::) PHPで後期静的結合(LSB)を実装し、クラスを定義するのではなく、静的コンテキストで呼び出しクラスを参照できるようにします。 1)解析プロセスは実行時に実行されます。2)継承関係のコールクラスを検索します。3)パフォーマンスオーバーヘッドをもたらす可能性があります。

PHPマジックメソッド(__construct、__destruct、__call、__get、__setなど)とは何ですか? PHPマジックメソッド(__construct、__destruct、__call、__get、__setなど)とは何ですか? Apr 03, 2025 am 12:03 AM

PHPの魔法の方法は何ですか? PHPの魔法の方法には次のものが含まれます。1。\ _ \ _コンストラクト、オブジェクトの初期化に使用されます。 2。\ _ \ _リソースのクリーンアップに使用される破壊。 3。\ _ \ _呼び出し、存在しないメソッド呼び出しを処理します。 4。\ _ \ _ get、dynamic属性アクセスを実装します。 5。\ _ \ _セット、動的属性設定を実装します。これらの方法は、特定の状況で自動的に呼び出され、コードの柔軟性と効率を向上させます。

一致式(PHP 8)とそれがスイッチとどのように異なるかを説明します。 一致式(PHP 8)とそれがスイッチとどのように異なるかを説明します。 Apr 06, 2025 am 12:03 AM

PHP8では、一致式は、式の値に基づいて異なる結果を返す新しい制御構造です。 1)Switchステートメントに似ていますが、実行ステートメントブロックの代わりに値を返します。 2)一致式の式は厳密に比較され、セキュリティが向上します。 3)スイッチステートメントの脱落の可能性を回避し、コードのシンプルさと読みやすさを向上させます。

フロントエンドからバックエンドの開発に変身すると、JavaやGolangを学ぶことはより有望ですか? フロントエンドからバックエンドの開発に変身すると、JavaやGolangを学ぶことはより有望ですか? Apr 02, 2025 am 09:12 AM

バックエンド学習パス:フロントエンドからバックエンドへの探査の旅は、フロントエンド開発から変わるバックエンド初心者として、すでにNodeJSの基盤を持っています...

クロスサイトリクエストフォーファリー(CSRF)とは何ですか?また、PHPにCSRF保護をどのように実装しますか? クロスサイトリクエストフォーファリー(CSRF)とは何ですか?また、PHPにCSRF保護をどのように実装しますか? Apr 07, 2025 am 12:02 AM

PHPでは、予測不可能なトークンを使用して、CSRF攻撃を効果的に防ぐことができます。特定の方法には次のものが含まれます。1。フォームのCSRFトークンを生成および埋め込みます。 2.リクエストを処理するときにトークンの有効性を確認します。

GOのどのライブラリが大企業によって開発されていますか、それとも有名なオープンソースプロジェクトによって提供されていますか? GOのどのライブラリが大企業によって開発されていますか、それとも有名なオープンソースプロジェクトによって提供されていますか? Apr 02, 2025 pm 04:12 PM

大企業または有名なオープンソースプロジェクトによって開発されたGOのどのライブラリが開発されていますか? GOでプログラミングするとき、開発者はしばしばいくつかの一般的なニーズに遭遇します...

PHPで厳密なタイプ(declare(strict_types = 1);)を説明します。 PHPで厳密なタイプ(declare(strict_types = 1);)を説明します。 Apr 07, 2025 am 12:05 AM

PHPの厳格なタイプは、declare(strict_types = 1)を追加することで有効になります。ファイルの上部に。 1)関数パラメーターのタイプチェックと戻り値を強制して、暗黙の型変換を防ぎます。 2)厳格なタイプを使用すると、コードの信頼性と予測可能性を改善し、バグを減らし、保守性と読みやすさを向上させることができます。

See all articles