好奇心と専門的成長の交差点にいる開発者向けに設計されたこの入門書は、非同期プログラミングによってアプリケーションのパフォーマンス、スケーラビリティ、応答性を向上させる方法を明らかにすることを目的としています。非ブロッキング操作とイベント ループの普遍的な原則に焦点を当てることで、AsyncIO、Node.js、Go などの特定のテクノロジーの枠を超えていきます。
この調査は、複雑な技術用語を使わずに、最新のソフトウェアを推進する効率性を理解したいソフトウェア開発者向けに作成されています。
リクエストを処理する単一のスレッドが、混雑した都市の 1 車線道路に似ていると考えてください。各リクエストは 1 台の車であり、車線が 1 つしかない場合、車が列をなして遅延が発生します。しかし、私たちの都市、つまり私たちのサービスが交通をより巧みに管理できたらどうなるでしょうか。ここで、非同期ランタイムの魔法が役立ちます。これは、都市にインテリジェントな交通システムを追加し、複数の車線や交差点を待たずに車を誘導するようなものです。
このシステムにより、交通の流れがスムーズになり、車 (またはタスク) が長時間待機することがなくなります。これはまさに、非同期ランタイムがソフトウェアを効率的に実行し続ける仕組みです。
I/O 操作を同期的に完了するサービスの例を考えてみましょう。わかりやすくするために、これらの操作は図の実行のメイン フローの外側に示されています。
サービスの起動フェーズ中に I/O をブロックすることは許容されるかもしれませんが、外部リクエストを処理するときはこのアプローチを避けることをお勧めします。次の図は、非ブロッキング I/O 操作の採用によってサービス効率がどのように向上するかを示しています。
これらの例は、サーバーのパフォーマンス向上が最大化されるシナリオを示しています。ただし、非ブロッキング操作の利点は、受信リクエストの頻度に関係なく持続します。理想的とは言えない状況でも、専用の I/O スレッドを処理ワークフローに統合することでパフォーマンスが向上します。
すべてのリクエストを処理するのに十分なスレッドがあれば、リクエストの処理に必要な合計時間 (クライアントの最初のリクエストから最終応答まで、右側の青い数字で示される) は必ず短縮されます。最悪の場合でも、この時間は同期処理方法の所要時間を超えることはありません。
次に、多くの開発者にとって直感に反するように思える方法に遭遇します。I/O 操作がリクエスト処理時間の大部分を占める場合、他のコード セグメントを最適化すると、わずかな改善が得られる可能性があります。キャッシュからデータを取得する時間は、ビジネス ロジックとテンプレートのレンダリングに費やされる時間とほぼ一致する可能性があります。
キャッシュまたはインプロセス データベースを使用すると、他の処理アクティビティと比較してデータの取得時間を短縮できます。
コードを効果的にセグメント化し、コールバックの実行を容易にするために、ランタイムに次のイベント ループ サイクルに進むように指示することができます。以下は、この概念の適用例です。
// blocking callbacks function func1_cb(str, cb) { var res = func1(str); cb(res); } function func2_cb(str, cb) { var res = func2(str); cb(res); } // non-blocking callbacks function func1_cb(str, cb) { var res = func1(str); process.nextTick(function () { cb(res); }); } function func2_cb(str, cb) { var res = func2(str); process.nextTick(function () { cb(res); }); } // usage example func1_cb(content, function (str) { func2_cb(str, function (result) { // work with result }); });
この方法論を採用して計算を 2 つの部分に分割すると、ほぼ同時にリクエストが到着するシナリオの全体的な処理時間は変わりません。ただし、最初のリクエストへの応答は遅延します。
このシナリオは、「次のティック」戦略を採用した場合の最も好ましくない結果を表しています。最初の例で示したように、「次のティック」方式は、頻度の低いリクエストには適しています。リクエストが中程度のペースで到着する場合、この手法を利用すると、実行の中断中に新しいリクエストの開始と非ブロッキング操作の開始をインターリーブできるため、処理速度が向上します。このアプローチにより、合計処理時間とリクエストあたりの平均時間の両方が効果的に短縮されます。
結論として、非ブロッキング I/O の採用は、アプリケーションのパフォーマンスを向上させるために重要であり、受信リクエストのボリュームがまばらな環境と大量の環境の両方で有益です。さらに、実行フローを効果的に順序付けると (「次のティック」手法に似た概念で示される)、サーバーの効率が大幅に向上します。これらの非同期プログラミング手法を採用すると、従来の同期方式に比べて明らかに有利になります。