これまでは、httpリクエストの提供に適用されるため、asynchronous
とnon-blocking i/o
という用語は同じことを意味すると思っていました。しかし、どうやら、それらはサーブレット3.0と3.1でそれぞれ別々に実装されています。ここで違いを理解するのに苦労しています...
誰かがこのトピックにもっと光を当てることができますか?具体的には、サーバーのサーブレット3.0実装が非同期でありながらスレッドでブロックされる例を探しています。私がこれを理解すれば、サーブレット3.1のノンブロッキングI/Oが解決しようとしている正確な問題を理解する方が簡単かもしれません。
学んだことをまとめてみます。サーブレット3.0とサーブレット3.1が解決する問題を理解するために、次のように見てみましょう。
Servlet 3.0より前:
リクエストの同期処理の問題は、応答が送信される前にスレッドが長時間実行されることになることです。これが大規模に発生すると、サーブレットコンテナは最終的にスレッドを使い果たします-長時間実行されているスレッドはスレッドの枯渇につながります。
サーブレット3.0より前のバージョンでは、これらの長時間実行されるスレッド用のコンテナー固有のソリューションがあり、別のワーカースレッドを生成して重いタスクを実行し、応答をクライアントに返すことができました。ワーカースレッドを開始すると、サーブレットスレッドはサーブレットプールに戻ります。 Tomcatのコメット、WebLogicのFutureResponseServlet、WebSphereの非同期リクエストディスパッチャは、非同期処理の実装例の一部です。
(詳細は link 1 を参照してください。)
サーブレット3.0非同期:
実際の作業は、(コンテナー固有のソリューションとは無関係に)スレッドプールの実装に委任できます。 Runnable
実装は実際の処理を実行し、AsyncContext
を使用してリクエストを別のリソースにディスパッチするか、レスポンスを書き込みます。 AsyncListenerオブジェクトをAsyncContextオブジェクトに追加して、コールバックメソッドを実装することもできます。
(詳細は link 1 を参照してください。)
サーブレット3.1 NIO:
上記のように、サーブレット3.0は非同期リクエスト処理を許可しましたが、許可されたのは(NIOではなく)従来のI/Oのみでした。従来のI/Oが問題になるのはなぜですか?
従来のI/Oでは、次の2つのシナリオを検討する必要があります。
ServletOutputStream
に書き込まれたサーバーからの応答データが遅い場合、クライアントスレッドは待機する必要があります。どちらの場合も、サーバースレッドは従来のI/O(要求/応答用)ブロックを実行します。つまり、サーブレット3.0では、リクエスト処理部分のみが非同期になり、リクエストとレスポンスを処理するためのI/Oは非同期になりませんでした。十分な数のスレッドがブロックすると、スレッドが枯渇し、パフォーマンスに影響します。
サーブレット3.1 NIOでは、この問題はReadListener
およびWriteListener
インターフェースによって解決されます。これらはServletInputStream
とServletOutputStream
に登録されています。リスナーにはコールバックメソッドがあり、コンテンツの読み取りが可能になったときに呼び出されるか、I/Oスレッドでサーブレットコンテナーがブロックされていなくてもコンテンツを書き込むことができます。したがって、これらのI/Oスレッドは解放され、パフォーマンスを向上させる他の要求に対応できるようになります。 (詳細は link 2 を参照してください。)
クレジット