マルチスレッド環境でのHttpClientを使用するためのベストプラクティス
-
16-09-2019 - |
質問
しばらくの間、私は、マルチスレッド環境でのHttpClientを使用しています。すべてのスレッドでは、それが接続を開始するとき、それは完全に新しいのHttpClientインスタンスを作成します。
最近、私はこのアプローチを使用することによって、それはユーザーがあまりにも多くのポートが開かれている持たせることができることを発見した、との接続のほとんどは、TIME_WAIT状態になっている。
ます。http://www.opensubscriber。 com/message/commons-httpclient-dev@jakarta.apache.org/86045.htmlする
このため、代わりに各スレッドで行うのでます:
HttpClient c = new HttpClient();
try {
c.executeMethod(method);
}
catch(...) {
}
finally {
method.releaseConnection();
}
私たちは持っていることを計画ます:
[方法A]
// global_c is initialized once through
// HttpClient global_c = new HttpClient(new MultiThreadedHttpConnectionManager());
try {
global_c.executeMethod(method);
}
catch(...) {
}
finally {
method.releaseConnection();
}
通常の状況では、global_cは、同時に50件の++スレッドによってアクセスされます。私は、これは任意のパフォーマンスの問題を作成し、不思議でしたか? MultiThreadedHttpConnectionManagerは、そのスレッドセーフなポリシーを実装するためにロックフリーのメカニズムを使用していますか?
10件のスレッドがglobal_cを使用している場合は、他の40件のスレッドがロックされるのですか?
またはすべてのスレッドで、私はHttpClientをのインスタンスを作成しますが、明示的に接続マネージャを解放し、場合、それが良いでしょう?
〔方法B〕
MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManager();
HttpClient c = new HttpClient(connman);
try {
c.executeMethod(method);
}
catch(...) {
}
finally {
method.releaseConnection();
connman.shutdown();
}
パフォーマンスの問題を被る()connman.shutdownのでしょうか?
私は50個の++のスレッドを使用してアプリケーションのための、優れている方法(AまたはB)を知ることはできますか?
解決 2
方法Aは、HTTPClientの開発者コミュニティによって推奨されます。
//www.mail-:HTTPを参照してください詳細はarchive.com/httpclient-users@hc.apache.org/msg02455.htmlするます。
他のヒント
確かに方法Aそのプールし、スレッドセーフであるためます。
あなたはHTTPClientの4.xを使用している場合は、、接続マネージャが呼び出されたの ThreadSafeClientConnManager の。 "までスクロール(詳細については、このリンクを参照してください。プーリング接続マネージャ」)。たとえばます:
HttpParams params = new BasicHttpParams();
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
ClientConnectionManager cm = new ThreadSafeClientConnManager(params, registry);
HttpClient client = new DefaultHttpClient(cm, params);
ドキュメントの私の読書は、HttpConnectionを自身がスレッドセーフとして扱われていないということであるので、MultiThreadedHttpConnectionManagerがHttpConnectionsの再利用可能なプールを提供し、あなたは、単一のMultiThreadedHttpConnectionManagerすべてのスレッドで共有され、一度だけ初期化されています。だから、オプションAに小さな改良のカップルを必要とします。
MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManag
良いかもしれfinallyブロックを使用して - 次に、各スレッドは、すべての要求のためのシーケンスを使用して、プールからのたっを取得し、その作業の完了に戻ってそれを置くべきです。 また、プールが使用可能な接続を持っていないとタイムアウト例外を処理している可能性をコードする必要があります。
HttpConnection connection = null
try {
connection = connman.getConnectionWithTimeout(
HostConfiguration hostConfiguration, long timeout)
// work
} catch (/*etc*/) {/*etc*/} finally{
if ( connection != null )
connman.releaseConnection(connection);
}
あなたは接続のプールを使用していると、あなたは、実際の接続を閉じることはありませんので、これはTIME_WAITの問題を打つべきではありません。このアプローチは、各スレッドが長い間の接続にハングアップしないことをassuumeありません。自身が開いたままにしているCONMANに注意します。
私はあなたがThreadSafeClientConnManagerを使いたいだろうと思います。
あなたが、それはここでどのように動作するかを見ることができます:ます。http: //foo.jasonhudgins.com/2009/08/http-connection-reuse-in-android.htmlする
または内部にそれを使用していますAndroidHttpClient
インチ
のHttpClient 4.5を使用すると、これを行うことができます
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(new PoolingHttpClientConnectionManager()).build();
これは、(接続マネージャをシャットダウンする)閉鎖可能を実現することに注意してください。