非同期PHP。 なんで?

画像



非同期プログラミングは、特にアプリケーションの応答性が特に重要であるWeb開発において、今日需要があります。 その時点でデータベースへのクエリを実行したり、電子メールを送信したり、時間がかかる他のタスクを処理したりしても、アプリケーションが「サグ」するまで誰も望みません。 クライアントは、何よりも自分の行動に対する答えをすぐに望んでいます。 アプリケーションの実行が遅い場合、顧客を失っています。 ホバリングアプリケーションに直面して、ほとんどの場合、ユーザーは単にそれを閉じて戻ることはありません。 ユーザーの観点からすると、アプリケーションはハングしたばかりで、これがなぜ発生したのか理解できません。複雑な操作を実行するのか、原則として動作を停止するのか。



Skyengバックエンド開発者Sergey Zhukによる記事の翻訳の紹介。



アプリの応答性



最近のアプリケーションはほとんどの場合応答しますが、ネットワーク、ファイルI / O、データベースのクエリを介したデータ交換などの一部のタスクまたは操作は時間がかかり、アプリケーションの速度が著しく低下する可能性があります。 そのような操作がアプリケーションをブロックするのを防ぐために、それらをバックグラウンドで実行して、それらが引き起こす遅延を隠すことができます。 同時に、アプリケーションは他のタスク、たとえば制御フローをユーザーインターフェイスに戻す、他のイベントに応答するなど、引き続き実行できるため、アプリケーションは応答性を維持します。



並行性と非同期性



非同期コードを見ると、ほとんどの場合、すぐに「すばらしい、プロセスを並列化できます!」と考えます。 失望するかもしれませんが、実際はそうではありません。 非同期性と並行性は同じものではありません。 この違いをつかむのは難しいので、理解してみましょう。



タスクが非同期で実行される場合、それらは互いにブロックせず、1つのタスクの実行は別のタスクの完了に依存しません。 次に、並行性には、独立した作業単位と同時にいくつかの個別のタスクを起動することが含まれます。



非同期性:

自分でタスクを完了してください 。 完了したら教えて、結果を見せてください。 現時点では、仕事を続けることができます。


非同期コードは、タスクの実行中に発生する依存関係の処理を必要とし、これはコールバックを使用して実装されます。 タスクが完了すると、コードは別のタスクに通知します。 非同期コードは、基本的にタスクが完了するまでの時間(イベントの順序)です。

画像

並行性:

必要な数のワーカーを雇い 、タスクを共有してより早く完了し、完了したら通知してください。 私は他のことを続けることができます。または、タスクが緊急の場合は、結果が返されるまで滞在して待機します。 その後、すべての従業員から最終結果を作成できます。 パラレル実行には多くの場合より多くのリソースが必要になるため、ここでは基本的にハードウェアに依存します。


画像

実際の例を使用して非同期実行と並列実行の違いを理解するために、2つの一般的なWebサーバーであるApacheとNginxを比較します。 彼らはこの違いを完璧に示しています。 Nginxはイベントベースの非同期モデルを使用し、Apacheは並列スレッドを使用します。 Apacheは追加の接続ごとに新しいスレッドを作成するため、ここで許可される接続の最大数はシステムで使用可能なメモリの量に依存します。 接続の制限に達すると、Apacheは追加の接続の作成を停止します。 Apacheを設定する際の制限要因はメモリです(多くの場合、並列実行はハードウェアに依存することに注意してください)。 スレッドが停止すると、クライアントはスレッドが解放されて応答を送信できるようになるまで応答を待ちます。



NginxはApacheのように機能しません-着信要求ごとに新しいスレッドを作成しません。 Nginxには、シングルスレッドのメインワークフロー(または複数のワーカー、多くの場合、1つのプロセッサに1つのワークフローがあります)があります。 このワーカーは、数千の接続を「同時に」処理でき、複数のスレッドで並行してではなく、1つのスレッドで非同期的に処理します。



したがって、「非同期」はシステムを構築する方法であり、互いに独立したプロセスの構成です。 「並列実行」とは、複数のプロセスを同時に実行することを意味しますが、それらは関連している場合と関連していない場合があります。 非同期実行では、複数のタスクを一度に処理し、並列実行では、複数のプロセスを一度に開始します。 これは同じように見えるかもしれませんが、そうではありません。 非同期性は構造を記述し、並列性は実行方法を記述します。



非同期実行は、コンピューター上のI / Oデバイス(マウス、キーボード、ディスプレイ)と比較できます。 それらはすべてオペレーティングシステムによって制御されますが、それぞれがカーネルの独立した部分です。 これらのプロセスは非同期であり、並行することができますが、これは必要ありません。 したがって、一貫性を確保するために、これらの独立したパーツ間のリンクを作成して、それらを調整する必要があります。



このバックエンドはどうですか?



バックエンドでは応答性はそれほど重要ではないと言うことができます。 JavaScriptを使用したこれらのクールな非同期処理はすべてフリーエンドで発生し、サーバーはリクエストに応答するだけなので、フリーエンドはアプリケーションではなくアプリケーションの応答性に責任を負う必要があります。 はい、それは事実ですが、サーバーのタスクはAPI応答に限定されません。 場合によっては、ビデオのダウンロードなどの複雑なタスクを管理する必要があります。 この場合、応答性は重要な要因ではないかもしれませんが、アプリケーションがアイドル状態でなければならないため、リソースの不足が無駄になります。 ファイルシステム操作、ネットワークインタラクション、データベースクエリなどの完了を待つことができます。 多くの場合、これらのI / O操作は、たとえばビデオファイルを変換する場合など、プロセッサの計算に比べて非常に遅くなります。 そして、ファイルをゆっくり保存または読み取る間、プロセッサは有用な作業を行う代わりにスタンバイ状態になります。 すでにわかったように、待機する代わりに、これらのタスクをバックグラウンドで実行できます。 どうやって? どうぞ



非同期PHP



JavaScriptでは、そのままで、非同期コードを記述するためのネイティブサポートとソリューションを利用できます。 Node.jsもあり、非同期サーバーアプリケーションを作成できます。 JavaScriptでは、setTimeout()関数を使用して、非同期コードの例を示すことができます。

画像



このコードを実行すると、次のように表示されます。

画像



setTimeout()関数はコードをキューに送信し、現在のコールスタックの最後でコードを実行します。 これは、コードの同期フローを中断し、実行を遅らせることを意味します。 console.log()への2番目の呼び出しは、setTimeout()呼び出し内のキュー内の呼び出しの前に実行されます。



PHPはどうですか? PHPには、真の非同期コードを作成するための適切なツールがありません。 setTimeout()に相当するものはなく、コードを単純に遅延またはキューイングすることはできません。 それが、AmpやReactPHPのようなフレームワークとライブラリが登場し始めた理由です。 彼らのアイデアは、言語の低レベルの詳細を隠し、ユーザーに非同期コードを記述し、JavaScriptやNode.jsなどのプロセスの競争的な実行を制御できる高レベルのツールを提供することです。



Node.jsとGoがある場合、なぜPHPを使用する必要があるのですか?



この質問は、非同期PHPの場合によく発生します。 何らかの理由で、多くはPHPを使用して非同期コードを記述することに反対しています。 PHPの代わりにGoまたはNode.jsを使用することを常に推奨します。



assertchrisのツイートは、これらの状況を完全に説明しています。



画像



もちろん、PHPが作成されたばかりの頃は、PHPをプログラミング言語にして大規模で複雑なアプリケーションを作成する目的はありませんでした。 当時、誰もJavaScriptや非同期性について考えていませんでした。 しかし、非同期コードを作成するための独自の関数(stream_select()関数など)を既に持っている完全に異なるPHPがあります。



はい。GoまたはNode.jsを使用して非同期サーバーアプリケーションを作成できますが、これで常に問題が解決するわけではありません。 PHPの豊富な経験がある場合は、新しい言語とエコシステムを学ぶよりも、状況に適したライブラリとツールを簡単に学ぶ方がはるかに簡単です。 ReactPHPAmpなどのツールを使用すると、Node.jsで行うのと同じように非同期コードを作成できます。 これらのツールは非常に開発されており、安定したバージョンがあるため、運用環境で安全に使用できます。



CLIだけでなく



チャット、サーバーなどを書くつもりはありません。 サイトの速度を上げたいだけです。


非同期コードはCLIスクリプトでのみ使用できることが一般に受け入れられています。 一部の非同期コンポーネントを従来の同期環境、さらには従来のWebアプリケーションに統合することは絶対に正常です。 たとえば、リクエストを受信し、複数の異なるリソースを非同期的に呼び出すことができます。これらの呼び出しが完了すると、リクエストとレスポンスのライフサイクルを継続でき、その結果、ページが高速に表示されます。



または、いくつかの外部API呼び出しを行う必要があります。たとえば、ユーザーが支払いを完了したときに、電子メールまたはプッシュ通知を送信する必要があります。 これらのAPI呼び出しを非同期で行い、その後、従来の同期コードストリームを継続できます。 アプリケーションを完全に書き直し、速度が低下するものをすべて削除する必要はありません。 パフォーマンスを妨げるボトルネックを特定するだけで、非同期コードを使用して修正できます。



はい、ほとんどの場合、非同期コードは引き続きCLIスクリプトで使用されますが、リアルタイムチャットとサーバーに限定されません。 サイトの速度を上げたいだけであれば、SymfonyまたはLaravelフレームワークを放棄して独自の完全に非同期のアプリケーションサーバーを作成する必要はありません。



おわりに



新しいパラダイムを学ぶことを恐れないでください。 PHPは、「スクリプトを実行し、コードを実行し、死ぬ」だけではありません。 慣れ親しんだPHPをまったく新しい方法で使用できることに気づいたとき、驚くでしょう。 非同期コードとイベント指向プログラミングにより、PHPの理解と、この言語を使用する可能性が広がります。 「PHPは不適切なツールである」または「これを常に行ってきましたが、改善できない」という理由だけで、非同期アプリケーションを作成するための新しい言語を学ぶ必要はありません 試してみてください!



まあ、私たちは開発者にとって常に多くの興味深い空席があることを思い出させてくれます!



All Articles