0

我正在使用 Apache 的 HttpAsyncClient 将传入请求代理或中继到另一台服务器。我有一个简单的案例(下面的示例代码)。

问题是Future<HttpResponse>它将把响应保存在内存中,等到它完成读取后再完成。我们有一些响应体非常大的调用,所以我想做的是“管道”或“零复制”策略,我只是在它们到来时传递正文内容,而不会将整个响应保存在内存中。

Apache Http Client 提供了一个ZeroCopyPostand ZeroCopyConsumer,但它们在Files而不是流(即响应的 OutputStream)上进行操作。

如何编写代码以将远程响应中的字节直接传递回原始响应?

到目前为止我的代码:

    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

So vanOekel's comment gave me the hint I needed; based on the example he linked, I created a "PipelineStreamConsumer" and then used that in the httpClient.execute(...) call.

I'm posting this for posterity, and in case someone wants to score some points with a better answer.

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 回答