0

Apache の HttpAsyncClient を使用して、着信要求を別のサーバーにプロキシまたはリレーしています。簡単なケースが機能しています(以下のサンプルコード)。

問題は、Future<HttpResponse>が応答をメモリに保持し、読み取りが完了するまで待機してから完了することです。非常に大きな応答本文を持つ呼び出しがいくつかあるので、私がやりたいのは、応答全体をメモリに保持せずに、本文のコンテンツを受信したときに渡すだけの「パイプライン」または「ゼロコピー」戦略です。

Apache Http Client はZeroCopyPostと を提供しますが、これらはストリーム (つまり、応答の OutputStream) ではなくZeroCopyConsumer動作します。Files

リモート応答からのバイトを元の応答に直接戻すコードを作成するにはどうすればよいですか?

これまでの私のコード:

    try {
        httpClient.start();

        Future<HttpResponse> future = httpClient.execute(method, null);
        HttpResponse remoteResponse = future.get();

        relayStatus(remoteResponse, originalResponse);
        relayHeaders(remoteResponse, originalResponse);
        relayBody(remoteResponse, originalResponse);
    }

    catch (IOException | InterruptedException |ExecutionException  e) {
        ...
    }

これを行うための直接的なサンプル コードを見つけるのに苦労していますが、コメントにリンクされているサンプルは、さらに多くのことを教えてくれます。答えはAsyncByteConsumerを使用することに沿っていると思います

私は正しい軌道に乗っていますか?ゼロコピー戦略を使用して、中継された応答から元の応答にボディバイトを渡すように拡張するにはどうすればよいですか?

4

1 に答える 1

1

したがって、vanOekel のコメントは、必要なヒントを与えてくれました。彼がリンクした例に基づいて、「PipelineStreamConsumer」を作成し、それをhttpClient.execute(...)呼び出しで使用しました。

後世のためにこれを投稿しています。誰かがより良い答えでいくつかのポイントを獲得したい場合に備えて。

Future<HttpResponse> future = httpClient.execute(producer, new PipelineStreamConsumer(originalResponse), null);

...

public class PipelineStreamConsumer extends AsyncByteConsumer<HttpResponse> {

    private final HttpServletResponse response;
    private HttpResponse remoteResponse;

    public PipelineStreamConsumer(HttpServletResponse response) {
        this.response = response;
    }

    @Override
    protected void onResponseReceived(HttpResponse remoteResponse) throws HttpException,
    IOException {
        this.remoteResponse = remoteResponse;
        relayStatus(remoteResponse);
        relayHeaders(remoteResponse);
    }

    @Override
    protected HttpResponse buildResult(HttpContext context) throws Exception {
        return remoteResponse;
    }

    @Override
    protected void onByteReceived(ByteBuffer buffer, IOControl control)
            throws IOException {
        WritableByteChannel channel = Channels.newChannel(outputStream);
        channel.write(buffer);
    }
}
于 2015-01-16T00:48:21.780 に答える