【问题标题】:Netty: Difference between using sync() and addListener()Netty:使用 sync() 和 addListener() 的区别
【发布时间】:2019-07-10 04:57:54
【问题描述】:

在服务器处理程序中,我有以下方法:

private void writeResponse(HttpObject currentObj, ChannelHandlerContext ctx) throws Exception {
    Promise<String> promise = client.run(); // client.run() will return a promise
    // the promise contains the result string I need for http response.
    promise.sync();
    // this method sends http response back, promise.getNow() is the content for the response.
    writeResponse(currentObj, ctx, promise.getNow()); 

}

此方法是在从客户端获取一些数据后发送响应(代码中的client)。当我使用浏览器对此进行测试时,我确实得到了响应内容。

但是,当我将其更改为:

private boolean writeResponse(HttpObject currentObj, ChannelHandlerContext ctx) throws Exception {
    Promise<String> promise = client.run();
    promise.addListener(new FutureListener<String>() {
        @Override
        public void operationComplete(Future<String> future) throws Exception {
            if (future.isSuccess()) {
                writeResponse(currentObj, ctx, future.getNow()); // (1)
            } else {
                writeResponse(currentObj, ctx, "FAILED");
            }
        }
    });
}

它不再起作用了。据我了解,它认为第二个也应该起作用,因为我已经确认代码确实进入了 (1) 块(if (future.isSuccess()) 块)。但是我在浏览器中没有得到任何响应。谁能解释一下或指出一些参考资料?我在文档中找到了await()addListener之间的比较,但它让我感觉两者在功能上彼此相似。

谢谢!

[update] 我发现这是因为这个重载方法:

private void writeResponse(HttpObject currentObj, ChannelHandlerContext ctx, String content) {
    FullHttpResponse response = new DefaultFullHttpResponse(
            HTTP_1_1, currentObj.decoderResult().isSuccess()? OK : BAD_REQUEST,
            Unpooled.copiedBuffer(content, CharsetUtil.UTF_8));

    response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");

    if (HttpUtil.isKeepAlive(request)) {
        // Add 'Content-Length' header only for a keep-alive connection.
        response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
        response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
    }
    ctx.write(response);
}

我不应该使用 ctx.write(response),而是使用 ctx.writeAndFlush(response)。

起初我使用 ctx.write(response) 因为我有 readComplete 方法为我做刷新。

public void channelReadComplete(ChannelHandlerContext ctx) {
    ctx.flush();
}

但似乎当使用addListener 而不是sync 时,channelReadComplete 无法进行刷新。知道为什么吗?

【问题讨论】:

  • 在运行操作之前不需要添加FutureListener吗?
  • @JamesKPolk 很抱歉没有清楚地表达我的代码。 client.run() 将返回一个包含我需要的结果字符串的承诺。所以我想我先得到promise,然后在它完成后,执行回调函数。还是这种情况下不会执行addListener的回调?
  • 你的代码很清楚,我只是糊涂了。很抱歉提供了不好的信息。
  • writeResponse 在做什么?
  • @Norman Maurer 这个 writeResponse(HttpObject, ChannelHandlerContext, String ) 应该将 HTTP 响应写回客户端。

标签: java asynchronous netty


【解决方案1】:

问题是你只是在ChannelFutureListener 中调用write(...) 而不是writeAndFlush(...)。因此,您的写入数据将永远不会刷新到套接字。

channelReadComplete(...) 可能在 ChannelFutureListener 执行之前被触发,所以你最终会遇到这种情况。

所以为了简短起见,请在侦听器中使用writeAndFlush(...)

【讨论】:

    猜你喜欢
    • 2015-01-21
    • 1970-01-01
    • 2017-08-04
    • 1970-01-01
    • 2022-01-21
    • 2017-11-16
    • 2015-11-02
    • 2013-02-21
    • 2011-08-08
    相关资源
    最近更新 更多