Netty:使用 sync() 和 addListener() 的区别
Netty: Difference between using sync() and addListener()
在服务器处理程序中,我有以下方法:
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
不能进行刷新。知道为什么吗?
问题是您只是在 ChannelFutureListener
中调用 write(...)
而不是 writeAndFlush(...)
。因此,您写入的数据永远不会刷新到套接字。
channelReadComplete(...)
可能会在 ChannelFutureListener
执行之前触发,所以你会遇到这种情况。
因此,为了使其更短,请在侦听器中使用 writeAndFlush(...)
。
在服务器处理程序中,我有以下方法:
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
不能进行刷新。知道为什么吗?
问题是您只是在 ChannelFutureListener
中调用 write(...)
而不是 writeAndFlush(...)
。因此,您写入的数据永远不会刷新到套接字。
channelReadComplete(...)
可能会在 ChannelFutureListener
执行之前触发,所以你会遇到这种情况。
因此,为了使其更短,请在侦听器中使用 writeAndFlush(...)
。