简体   繁体   English

使用 Netty 限制 HTTP/2 中的流读取

[英]Throttling reads on streams in HTTP/2 with Netty

In the Netty 4 proxy example AUTO_READ is turned off, which according to this answer is so that a channel sending a lot of data to the proxy doesn't use up too many buffers, which makes sense.在 Netty 4 代理示例中AUTO_READ 被关闭,根据这个答案是为了向代理发送大量数据的通道不会占用太多缓冲区,这是有道理的。

However, my understanding is that in HTTP/2 you should never delay reads, and instead deal with the flow control on a stream-by-stream basis.但是,我的理解是,在 HTTP/2 中,您永远不应该延迟读取,而是逐个流地处理流量控制。 I can't figure out how to do this in Netty though.我不知道如何在 Netty 中做到这一点。

It feels like it should be achieved by returning 0 in onDataRead on an Http2ConnectionHandler .感觉应该通过在onDataRead上的Http2ConnectionHandler返回 0 来实现。 The following contrived example is how I expected it to work, where the bytes are not consumed for 100ms:以下人为示例是我期望它的工作方式,其中 100 毫秒不消耗字节:

@Override
public int onDataRead(ChannelHandlerContext ctx, int streamId, ByteBuf data,
                      int padding, boolean endOfStream) throws Http2Exception {
    int processed = data.readableBytes() + padding;

    Http2LocalFlowController flowController = decoder().flowController();
    Http2Stream stream = connection().stream(streamId);
    executorService.schedule(() -> {
        ctx.executor().execute(() -> {
            try {
                // ...do stuff...
                flowController.consumeBytes(stream, processed);
            } catch (Http2Exception e) {
                e.printStackTrace(); // now what?
            }
        });
    }, 100, TimeUnit.MILLISECONDS);

    return 0;
}

When I use this, no exception is thrown, and the client just times out.当我使用它时,不会抛出任何异常,客户端只是超时。 (Note that if I call the consumeBytes call before returning from onDataRead then it does work.) (请注意,如果我在从onDataRead返回之前调用consumeBytes调用,那么它确实有效。)

With some extra logging, when reading 16k messages I can see immediately that 65535 bytes are unconsumed.通过一些额外的日志记录,在读取 16k 条消息时,我可以立即看到 65535 字节未被消耗。 After beginning to consume, a window frame is reportedly sent after 32k.开始消费后,据报道在32k后发送一个窗口框架。 After the 4th message, flowController.unconsumedBytes(stream) reports 0 bytes unconsumed, however the next message never comes to onDataRead .在第 4 条消息之后, flowController.unconsumedBytes(stream)报告 0 字节未使用,但是下一条消息永远不会出现在onDataRead

This apparently works for other people so I'm struggling to see where the issue is.这显然适用于其他人,所以我正在努力找出问题所在。

The consumeBytes method returns a boolean that indicates whether or not a threshold was reached meaning a window update can be sent for the stream (ie to say that the stream can send more data). consumeBytes方法返回一个布尔值,指示是否达到阈值意味着可以为流发送窗口更新(即说流可以发送更多数据)。

The method does a ctx.write with the window update frame, but doesn't flush it.该方法对窗口更新框架执行ctx.write ,但不刷新它。 So if nothing is flushing the context, you need to do that:因此,如果没有任何内容刷新上下文,您需要这样做:

if (flowController.consumeBytes(stream, processed)) {
    ctx.flush();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM