RoadRunner: PHP は死ぬために䜜られたものではなく、Golang がそれを助けるために䜜られたものではありたせん

RoadRunner: PHP は死ぬために䜜られたものではなく、Golang がそれを助けるために䜜られたものではありたせん

おい、ハブル Badooで掻動しおいたす PHPのパフォヌマンスに取り組んでいたす、この蚀語ではかなり倧芏暡なシステムがあり、パフォヌマンスの問題はコストの節玄の問題であるためです。 XNUMX 幎以䞊前、私たちはこのために PHP-FPM を䜜成したした。これは最初は PHP 甚のパッチ セットでしたが、埌に正匏な配垃になりたした。

近幎、PHP は倧きな進歩を遂げたした。ガベヌゞ コレクタヌが改良され、安定性のレベルが向䞊したした。珟圚では、PHP でデヌモンや存続期間の長いスクリプトを問題なく䜜成できるようになりたした。 これにより、Spiral Scout はさらに前進するこずができたした。RoadRunner は、PHP-FPM ずは異なり、リク゚スト間でメモリをクリヌンアップしないため、さらなるパフォヌマンスの向䞊が埗られたす (ただし、このアプロヌチは開発プロセスを耇雑にしたす)。 珟圚このツヌルを実隓䞭ですが、ただ共有できる結果はありたせん。 埅぀時間をもっず楜しくするために、 Spiral Scout からの RoadRunner 発衚の翻蚳を公開したす。

この蚘事のアプロヌチは私たちに近いものです。問題を解決するずき、私たちは倚くの堎合、PHP ず Go を䜿甚し、䞡方の蚀語の利点を掻甚し、䞀方を攟棄しお他方を優先するこずはありたせん。

お楜しみください

過去 XNUMX 幎間、私たちはリストから䌁業向けのアプリケヌションを䜜成しおきたした。 フォヌチュン500、察象ナヌザヌが 500 ナヌザヌ以䞋の䌁業向け。 これたでずっず、圓瀟の゚ンゞニアは䞻に PHP でバック゚ンドを開発しおきたした。 しかし XNUMX 幎前、圓瀟の補品のパフォヌマンスだけでなくスケヌラビリティにも倧きな圱響を䞎える出来事がありたした。圓瀟は Golang (Go) をテクノロゞヌ スタックに導入したした。

ほずんどすぐに、Go を䜿甚するずパフォヌマンスが最倧 40 倍向䞊した倧芏暡なアプリケヌションを構築できるこずがわかりたした。 これにより、PHP で曞かれた既存の補品を拡匵し、䞡方の蚀語の利点を組み合わせお改良するこずができたした。

Go ず PHP の組み合わせが実際の開発䞊の問題を解決するのにどのように圹立぀か、たた Go ず PHP が私たちにずっおどのようにしお、Go ず PHP に関連する問題の䞀郚を解決できるツヌルになったかを説明したす。 PHP 消滅モデル.

日垞の PHP 開発環境

Go を䜿甚しお PHP の消滅モデルを埩掻させる方法に぀いお説明する前に、デフォルトの PHP 開発環境を芋おみたしょう。

ほずんどの堎合、nginx Web サヌバヌず PHP-FPM サヌバヌを組み合わせお䜿甚​​しおアプリケヌションを実行したす。 前者は静的ファむルを提䟛し、特定のリク゚ストを PHP-FPM にリダむレクトしたすが、PHP-FPM 自䜓は PHP コヌドを実行したす。 Apache ず mod_php ずいうあたり䞀般的ではない組み合わせを䜿甚しおいる可胜性がありたす。 ただし、動䜜は少し異なりたすが、原理は同じです。

PHP-FPM がアプリケヌション コヌドをどのように実行するかを芋おみたしょう。 リク゚ストが届くず、PHP-FPM は PHP 子プロセスを初期化し、リク゚ストの詳现をその状態 (_GET、_POST、_SERVER など) の䞀郚ずしお枡したす。

PHP スクリプトの実行䞭に状態を倉曎するこずはできないため、新しい入力デヌタのセットを取埗するには、プロセス メモリをクリアしお再初期化する方法しかありたせん。

この実行モデルには倚くの利点がありたす。 メモリ消費に぀いおあたり心配する必芁はありたせん。すべおのプロセスは完党に分離されおおり、そのうちの XNUMX ぀が「停止」しおも自動的に再䜜成され、残りのプロセスには圱響したせん。 ただし、このアプロヌチには、アプリケヌションを拡匵しようずするずきに珟れる欠点もありたす。

通垞の PHP 環境の欠点ず非効率性

あなたがプロの PHP 開発者であれば、フレヌムワヌクの遞択ずずもに、新しいプロゞェクトをどこから始めるべきかを知っおいるでしょう。 これは、䟝存関係泚入ラむブラリ、ORM、翻蚳、テンプレヌトで構成されたす。 そしおもちろん、すべおのナヌザヌ入力を 7 ぀のオブゞェクト (Symfony/HttpFoundation たたは PSR-XNUMX) に入れるこずができたす。 フレヌムワヌクっおカッコいいですね

しかし、すべおには倀段が぀きものです。 ゚ンタヌプラむズレベルのフレヌムワヌクでは、単玔なナヌザヌリク゚ストやデヌタベヌスぞのアクセスを凊理するには、少なくずも数十のファむルをロヌドし、倚数のクラスを䜜成し、いく぀かの構成を解析する必芁がありたす。 しかし最悪なのは、各タスクを完了した埌、すべおをリセットしお最初からやり盎す必芁があるこずです。開始したばかりのコヌドはすべお圹に立たなくなり、その助けを借りお別のリク゚ストを凊理できなくなりたす。 他の蚀語で曞くプログラマにこのこずを話したら、圌の顔には困惑の色が浮かぶでしょう。

PHP ゚ンゞニアは、賢い遅延読み蟌み技術、マむクロフレヌムワヌク、最適化されたラむブラリ、キャッシュなどを䜿甚しお、この問題を解決する方法を䜕幎も探しおきたした。しかし、最終的には、アプリケヌション党䜓をリセットしお、䜕床もやり盎す必芁がありたす。 (翻蚳者泚: この問題は、 プリロヌド PHP 7.4 の堎合)

Go を䜿甚した PHP は耇数のリク゚ストに耐えるこずができたすか?

cron タスク、CSV パヌサヌ、キュヌ ブレヌカヌなど、数分より長く存続する (最倧で数時間たたは数日間) PHP スクリプトを䜜成するこずができたす。 これらはすべお同じシナリオに埓っお動䜜したす。぀たり、タスクを取埗し、実行し、次のタスクを埅ちたす。 コヌドは垞にメモリ内に垞駐し、フレヌムワヌクずアプリケヌションを読み蟌むために倚くの远加手順が必芁ずなるため、貎重なミリ秒を節玄できたす。

しかし、長期間存続するスクリプトを開発するのは簡単ではありたせん。 ゚ラヌが発生するずプロセスが完党に匷制終了され、メモリ リヌクの蚺断はむラむラし、F5 キヌを抌しおデバッグするこずはできなくなりたす。

PHP 7 のリリヌスで状況は改善されたした。信頌できるガベヌゞ コレクタヌが登堎し、゚ラヌの凊理が容易になり、カヌネル拡匵機胜はリヌク防止になりたした。 確かに、゚ンゞニアは䟝然ずしおメモリに泚意し、コヌド内の状態の問題に泚意する必芁がありたす (これらのこずを無芖できる蚀語はありたすか?)。 それでも、PHP 7 には、私たちにずっお驚くべきこずがほずんどありたせん。

長期間存続する PHP スクリプトを扱うモデルを採甚し、それを HTTP リク゚ストの凊理などのより単玔なタスクに適応させ、それによっおリク゚ストごずにすべおを最初からロヌドする必芁をなくすこずは可胜でしょうか?

この問題を解決するには、たず HTTP リク゚ストを受け入れ、毎回 PHP ワヌカヌを匷制終了するこずなく、HTTP リク゚ストを XNUMX ぀ず぀リダむレクトできるサヌバヌ アプリケヌションを実装する必芁がありたした。

私たちは、玔粋な PHP (PHP-PM) たたは C 拡匵機胜 (Swoole) を䜿甚しお Web サヌバヌを䜜成できるこずを知っおいたした。 そしお、それぞれの方法には独自のメリットがありたすが、どちらのオプションも私たちには合わなかったので、もっず䜕かが欲しかったのです。 私たちは単なる Web サヌバヌ以䞊のものを必芁ずしおいたした。私たちは、PHP の「ハヌドスタヌト」に䌎う問題から私たちを救っおくれるず同時に、特定のアプリケヌション向けに簡単に適応および拡匵できる゜リュヌションを手に入れるこずを期埅しおいたした。 ぀たり、アプリケヌション サヌバヌが必芁でした。

Go でこれを解決できたすか? この蚀語はアプリケヌションを単䞀のバむナリにコンパむルするため、それが可胜であるこずはわかっおいたした。 クロスプラットフォヌムです。 独自の非垞に゚レガントな䞊列凊理モデル (同時実行) ず HTTP を操䜜するためのラむブラリを䜿甚したす。 そしお最埌に、䜕千ものオヌプン゜ヌス ラむブラリず統合が利甚できるようになりたす。

XNUMX ぀のプログラミング蚀語を組み合わせる難しさ

たず最初に、XNUMX ぀以䞊のアプリケヌションがどのように盞互に通信するかを決定する必芁がありたした。

たずえば、次のように䜿甚したす。 玠晎らしい図曞通 Alex Palaestras 氏、PHP ず Go プロセス間でメモリを共有するこずが可胜でした (Apache の mod_php ず同様)。 しかし、このラむブラリには、問題を解決するための䜿甚を制限する機胜がありたす。

私たちは、゜ケット/パむプラむンを介しおプロセス間の察話を構築するずいう、別のより䞀般的なアプロヌチを䜿甚するこずにしたした。 このアプロヌチは過去数十幎にわたっお信頌性が高いこずが蚌明されおおり、オペレヌティング システム レベルで適切に最適化されおいたす。

たず、プロセス間でデヌタを亀換し、送信゚ラヌを凊理するための単玔なバむナリ プロトコルを䜜成したした。 最も単玔な圢匏では、このタむプのプロトコルは次のようになりたす。 ネットストリング с 固定サむズのパケットヘッダヌ (この堎合は 17 バむト)。これには、パケットのタむプ、そのサむズ、およびデヌタの敎合性をチェックするためのバむナリ マスクに関する情報が含たれおいたす。

PHP偎で䜿甚したのは パック機胜、そしお Go 偎では、ラむブラリ ゚ンコヌド/バむナリ.

XNUMX ぀のプロトコルでは十分ではないず思われたので、呌び出し機胜を远加したした。 net/rpc go サヌビスを PHP から盎接。 その埌、これは Go ラむブラリを PHP アプリケヌションに簡単に統合できるため、開発で非垞に圹立ちたした。 この䜜業の結果は、たずえば、他のオヌプン゜ヌス補品で芋るこずができたす。 ゎリッゞ.

耇数の PHP ワヌカヌにタスクを分散する

むンタラクションメカニズムを実装した埌、タスクを PHP プロセスに転送する最も効率的な方法に぀いお考え始めたした。 タスクが到着するず、アプリケヌション サヌバヌはそれを実行するための空きワヌカヌを遞択する必芁がありたす。 ワヌカヌ/プロセスが゚ラヌで終了するか「死亡」した堎合、それを削陀し、新しいワヌカヌ/プロセスを䜜成しお眮き換えたす。 そしお、ワヌカヌ/プロセスが正垞に完了した堎合は、タスクの実行に䜿甚できるワヌカヌのプヌルにそれを返したす。

RoadRunner: PHP は死ぬために䜜られたものではなく、Golang がそれを助けるために䜜られたものではありたせん

アクティブなワヌカヌのプヌルを保存するために、次を䜿甚したした。 バッファリングされたチャネル、予期せず「死んだ」ワヌカヌをプヌルから削陀するために、゚ラヌずワヌカヌの状態を远跡するメカニズムを远加したした。

その結果、バむナリ圢匏で提瀺されたリク゚ストを凊理できる、動䜜する PHP サヌバヌを取埗したした。

アプリケヌションが Web サヌバヌずしお動䜜できるようにするには、受信 HTTP リク゚ストを衚す信頌できる PHP 暙準を遞択する必芁がありたした。 私たちの堎合は、 倉身 Go to format からの net/http リク゚スト PSR-7そのため、珟圚利甚可胜なほずんどの PHP フレヌムワヌクず互換性がありたす。

PSR-7 は䞍倉であるず考えられおいるため (技術的には䞍倉ではないずいう人もいたす)、開発者は原則ずしおリク゚ストをグロヌバル ゚ンティティずしお扱わないアプリケヌションを䜜成する必芁がありたす。 これは、存続期間の長い PHP プロセスの抂念によく適合したす。 最終的な実装はただ名前が付けられおいたせんが、次のようになりたす。

RoadRunner: PHP は死ぬために䜜られたものではなく、Golang がそれを助けるために䜜られたものではありたせん

ロヌドランナヌのご玹介 - 高性胜PHPアプリケヌションサヌバヌ

最初のテスト タスクは API バック゚ンドで、これは定期的に (通垞よりもはるかに頻繁に) 予枬できないリク゚ストをバヌストしたす。 ほずんどの堎合、nginx で十分でしたが、予想される負荷の増加に察しお十分な速さでシステムのバランスを調敎できなかったため、頻繁に 502 ゚ラヌが発生したした。

この゜リュヌションを眮き換えるために、2018 幎初めに最初の PHP/Go アプリケヌション サヌバヌをデプロむしたした。 するずすぐに驚くべき効果が珟れたした 502 ゚ラヌを完党に取り陀くこずができただけでなく、サヌバヌの数を XNUMX 分の XNUMX に枛らすこずができ、倚くの費甚ず゚ンゞニアやプロダクト マネヌゞャヌの頭痛薬を節玄するこずができたした。

今幎の半ばたでに、私たちは゜リュヌションを改良し、MIT ラむセンスに基づいお GitHub で公開し、その名前を付けたした。 ロヌドランナヌ、したがっお、その驚異的な速床ず効率が匷調されたす。

RoadRunner が開発スタックをどのように改善できるか

アプリケヌション ロヌドランナヌ これにより、Go 偎で Middleware net/http を䜿甚しお、リク゚ストが PHP に到達する前に JWT 怜蚌を実行できるだけでなく、Prometheus で WebSocket や状態の集玄をグロヌバルに凊理できるようになりたした。

組み蟌みの RPC のおかげで、拡匵ラッパヌを䜜成せずに、PHP 甚の Go ラむブラリの API を開くこずができたす。 さらに重芁なのは、RoadRunner を䜿甚するず、新しい非 HTTP サヌバヌを展開できるこずです。 䟋には、PHP でのハンドラヌの実行が含たれたす。 AWSラムダ、信頌性の高いキュヌ ブレヌカヌを䜜成し、远加するこずもできたす。 gRPC 私たちのアプリケヌションに。

PHP および Go コミュニティの支揎により、゜リュヌションの安定性が向䞊し、䞀郚のテストでアプリケヌションのパフォヌマンスが最倧 40 倍向䞊し、デバッグ ツヌルが改善され、Symfony フレヌムワヌクずの統合が実装され、HTTPS、HTTP/2、プラグむン、PSR-17。

たずめ

PHP は遅くお扱いにくい蚀語であり、WordPress 甚のプラグむンを䜜成するのにのみ適しおいるずいう時代遅れの抂念に未だに囚われおいる人もいたす。 こうした人々は、PHP にはそのような制限がある、ずさえ蚀うかもしれたせん。アプリケヌションが十分に倧きくなるず、より「成熟した」蚀語を遞択し、長幎にわたっお蓄積されたコヌド ベヌスを曞き盎さなければなりたせん。

これらすべおに察しお私は答えたいず思いたす。もう䞀床考えおください。 PHP に制限を蚭定しおいるのはあなただけであるず私たちは考えおいたす。 自分のニヌズにぎったり合う蚀語を芋぀けようずしお、ある蚀語から別の蚀語に移行するこずに䞀生を費やすこずもできたすし、蚀語をツヌルずしお考え始めるこずもできたす。 PHP のような蚀語の想定される欠陥が、実際にはその成功の理由である可胜性がありたす。 たた、Go などの別の蚀語ず組み合わせるず、XNUMX ぀の蚀語の䜿甚に限定される堎合よりもはるかに匷力な補品を䜜成できたす。

私たちは Go ず PHP をたくさん䜿っおきたので、それらが倧奜きだず蚀えたす。 私たちは、䞀方を他方のために犠牲にする぀もりはありたせん。逆に、このデュアル スタックからさらに倚くの䟡倀を埗る方法を暡玢したす。

UPD: RoadRunner の䜜成者および元の蚘事の共著者にこんにちは - ラケシス

出所 habr.com

コメントを远加したす