9

HTTPClient を使用して REST API を実装しています。

以下を使用してサーバーの応答を読み取っています。

method = new PostMethod(url);
HttpClient client = new HttpClient();
int statusCode = client.executeMethod(method);
String responseBody = method.getResponseBodyAsString();

これを行うと、次の警告が表示されます。

Dec 9, 2009 7:41:11 PM org.apache.commons.httpclient.HttpMethodBase getResponseBody
WARNING: Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended.

ドキュメントは続けて言います:

HttpClient は、効率的な要求/応答本文のストリーミングが可能です。大きなエンティティは、メモリにバッファリングされずに送信または受信される場合があります。これは、複数の HTTP メソッドが同時に実行される可能性がある場合に特に重要です。文字列やバイト配列などのエンティティを処理するための便利なメソッドがありますが、それらの使用はお勧めできません。注意して使用しないと、メモリ内の完全なエンティティのバッファリングを意味するため、メモリ不足の状態に簡単につながる可能性があります。

だから私の質問は、文字列として完全な応答が必要な場合 (つまり、DB に格納するため、または DOM を使用して解析するため)、ストリームを使用する方がメモリ効率が高いのはなぜですか?

4

4 に答える 4

15

エンティティ全体を文字列として取得するよりも、ストリームを使用する方が効率的です。

  1. コードに返す前に、応答の内容全体を読み取る必要があります。
  2. サーバーから応答全体が送信されるまで、制御をコードに戻すことはできません。

応答をストリームとして処理した場合、実際に行っているのは一度に N バイトずつ処理することです。これは、リモート サーバーがまだデータの次のセグメントを送り返している間に、最初の応答セグメントの処理を開始できることを意味します。したがって、ユースケースでデータを受信時に処理できる場合、これはアクセス方法としてより理にかなっています。

ただし、何らかの理由でレスポンス全体を文字列として必要とする場合、ストリーム メソッドのすべての効率性はまったく関係ありません。レスポンスを断片的に読み取ったとしても、レスポンス全体を待つ必要があるためです処理する前に、すべてを単一の文字列に含めます。

ストリームを使用する効率は、応答本文全体を取得する前に応答の処理を開始できるユースケースがある場合にのみ利用できます。

于 2009-12-10T01:00:52.410 に答える
4

プロセス全体のメモリ効率が向上するわけではありません。ストリームから読み取って文字列に入れると、プロセスを 2 つの部分に分けて、HttpClient クラスが認識しないようにするだけです。

文字列全体が本当に必要な場合は、警告を無視できます。サーバーが DoS 攻撃によって簡単に停止されないように、リクエストごとにメモリを使いすぎないようにするのはあなた次第です。

于 2009-12-10T00:57:38.613 に答える
2

あなたの質問は要点を混乱させます。

応答全体を文字列として絶対に必要とする場合は、それを行います。

ただし、それを回避できる場合は、ストリームを使用してください。

応答全体を文字列にロードすると、応答本文全体が一度にメモリに存在します。

ストリームを使用すると、一度にメモリに保持されるのは応答のごく一部のみです。

ドキュメントには、特に一度に複数の大きなリクエストがある場合、リクエスト本文全体を文字列にロードするには大量のメモリが必要になると書かれています。

于 2009-12-10T00:57:56.250 に答える
0

org.w3c.Documenta (またはさらに良いことに a ) に解析しているorg.jdom.Document場合、ストリームを直接使用するのは非常に簡単です。元:

org.apache.http.HttpResponse hr = httpClient.execute(httpRequest);
org.apache.http.HttpEntity he = hr.getEntity();
org.jdom.input.SAXBuilder builder = new SAXBuilder();
org.jdom.Document document = builder.build(he.getContent());
于 2009-12-10T01:07:12.413 に答える