【问题标题】:Handle HTTP client exception in netty在 netty 中处理 HTTP 客户端异常
【发布时间】:2017-04-08 17:36:02
【问题描述】:

我对 netty 比较陌生,不确定自己是否做对了。我会尽量简短。如果有任何不清楚的地方,请询问更多信息。

所以,我有一个服务 HTTP 请求的 netty 服务器,其中的内容应该是序列化为 Json 字符串的 protobuf 消息。

通道管道如下所示:

@Override protected void initChannel(final SocketChannel channel) throws Exception {
    final ChannelPipeline pipeline = channel.pipeline();
    pipeline.addLast(new HttpServerCodec());
    pipeline.addLast(new HttpObjectAggregator(1048576));
    pipeline.addLast(new HttpProtobufServerCodec(charset, requestConverter, responseConverter));
    pipeline.addLast(new ProtobufMessageHandler(mapping));
}

前两个通道处理程序是标准的 netty 东西,

HttpProtobufServerCodec 看起来像:

public class HttpProtobufServerCodec extends CombinedChannelDuplexHandler<HttpToProtobufDecoder, ProtobufToHttpEncoder>

和 HttpToProtobufDecoder 看起来像:

public final class HttpToProtobufDecoder extends MessageToMessageDecoder<FullHttpRequest> {
    private Charset charset;
    private final Converter<byte[], ?> converter;

    protected HttpToProtobufDecoder(final Charset charset, final Converter<byte[], ?> converter) {
        this.charset = charset;
        this.converter = converter;
    }

    @Override protected void decode(final ChannelHandlerContext ctx, final FullHttpRequest msg, final List<Object> out)
            throws Exception {
        byte[] payloadBytes = new byte[msg.content().readableBytes()];
        msg.content().readBytes(payloadBytes);
        Message message = (Message) converter.convert(payloadBytes);
        out.add(message);
    }

    @Override public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, 
                    HttpResponseStatus.BAD_REQUEST, 
                    Unpooled.wrappedBuffer(charset.encode("Could not read request!").array()));

        //ctx.writeAndFlush(response);
        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
    }
}

所以,我在 HttpToProtobufDecoder 中收到了 FullHttpRequest,并尝试将请求的内容解码为 protobuf 消息。如果无法解码内容,这将引发异常,这会将我们置于 exceptionCaught(...) 方法中。..

在异常捕获中创建 HTTP 400 响应并将其写入 channelHandlerContext。这就是我的问题所在。

如果以下几行的 cmets 被切换:

//ctx.writeAndFlush(response);
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);

客户端在读取响应正文时超时。但是如果我在写完 400 之后关闭频道,一切似乎都很好。会发生什么;输入流的读取被阻止,因为没有可用的输入数据。 IE。我们被困在下面的 in.read(...) 中,在客户端代码的某个地方:

while ((bytesRead = in.read(buffer)) != -1) {
        out.write(buffer, 0, bytesRead);
        byteCount += bytesRead;
    }

那么,问题是,你有没有因为某种原因在写了一个 http 400 响应后关闭了频道?

我是否以正确的方式进行此操作?我应该在 exceptionCaught 中写 HTTP 响应消息吗?

对不起,如果问题有点不清楚。任何帮助将不胜感激!

/谢谢!

【问题讨论】:

    标签: java http netty


    【解决方案1】:

    客户端无法知道您的消息何时已完全发送。添加内容长度或分块标题,您将不再需要关闭连接。

    【讨论】:

    • 谢谢!我自己得出了这个确切的结论。很高兴得到确认。我不知何故虽然 HttpServerCodec 会/应该处理那个。
    猜你喜欢
    • 2020-12-18
    • 2021-12-19
    • 1970-01-01
    • 2015-08-18
    • 1970-01-01
    • 1970-01-01
    • 2019-07-27
    • 2015-04-26
    • 1970-01-01
    相关资源
    最近更新 更多