Netty:使用sync()和addListener()之间的区别

时间:2019-02-16 03:34:29

标签: java asynchronous netty

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

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之间的比较,但给我的感觉是两者在功能上彼此相似。

谢谢!

[更新]我发现这是由于此重载方法引起的:

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无法进行刷新。知道为什么吗?

1 个答案:

答案 0 :(得分:0)

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

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

因此,请在监听器中短用writeAndFlush(...)