目录
1、异步核心组件
1.1 ChannelFuture
所有 Netty 的 I/O 操作都是异步的,返回 ChannelFuture
对象:
ChannelFuture future = bootstrap.connect("localhost", 8080);
future.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) {
System.out.println("连接成功");
} else {
System.err.println("连接失败");
future.cause().printStackTrace();
}
}
});
ChannelFuture 是一个接口 ,可以添加监听器,当监听的事件发生时,就会通知到监听器。
常用方法:
- sync 方法, 阻塞等待程序结果反回
- isDone 方法来判断当前操作是否完成;
- isSuccess 方法来判断已完成的当前操作是否成功;
- getCause 方法来获取已完成的当前操作失败的原因;
- isCancelled 方法来判断已完成的当前操作是否被取消;
- addListener 方法来注册监听器,当操作已完成(isDone 方法返回完成),将会通知指定的监听器;如果Future 对象已完成,则通知指定的监听器
1.2 Promise 与 Future
-
Future:只读的异步结果容器,ChannelFuture就是他的一个子接口
-
Promise:继承自Future,可写的 Future(Netty 扩展),
Promise
提供了方法让你(或者执行异步操作的实体)能够主动设置操作的最终结果(成功或失败)。从而可以构造异步操作链,一个操作的Promise
的结果可以作为触发下一个操作的输入,或者用于组合多个操作的结果。-
常用方法:
-
setSuccess(V result)
: 将Promise
标记为成功完成,并设置操作的结果值。 -
trySuccess(V result)
: 尝试将Promise
标记为成功完成。如果操作尚未完成(即Promise
状态还是未完成),则设置成功并返回true
;如果已经完成(无论成功或失败),则不做任何操作并返回false
。线程安全。 -
setFailure(Throwable cause)
: 将Promise
标记为失败完成,并设置失败的原因(异常)。 -
tryFailure(Throwable cause)
: 尝试将Promise
标记为失败完成。如果操作尚未完成,则设置失败并返回true
;如果已经完成,则不做任何操作并返回false
。线程安全。
-
-
EventLoop eventLoop = channel.eventLoop();
Promise<String> promise = eventLoop.newPromise();
// 在其他线程完成Promise
eventLoop.execute(() -> {
try {
Thread.sleep(1000);
promise.setSuccess("操作完成");
} catch (Exception e) {
promise.setFailure(e);
}
});
// 添加监听器
promise.addListener(future -> {
if (future.isSuccess()) {
System.out.println("结果: " + future.get());
}
});
2、异步处理流程
2.1 入站事件处理
public class MyInboundHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
// 异步处理消息
EventLoop eventLoop = ctx.channel().eventLoop();
eventLoop.execute(() -> {
try {
// 模拟耗时操作
Thread.sleep(1000);
ByteBuf buf = (ByteBuf) msg;
System.out.println("处理消息: " + buf.toString(CharsetUtil.UTF_8));
ctx.writeAndFlush("已处理: " + buf.toString(CharsetUtil.UTF_8));
} catch (Exception e) {
ctx.close();
}
});
}
}
2.2 出站异步操作
public class MyOutboundHandler extends ChannelOutboundHandlerAdapter {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
// 异步写入
ctx.executor().execute(() -> {
try {
// 模拟处理
Thread.sleep(500);
System.out.println("异步写入数据");
ctx.write(msg, promise);
} catch (InterruptedException e) {
promise.setFailure(e);
}
});
}
}
3、性能优化
3.1 避免阻塞 EventLoop
-
长时间运行的任务应该提交到专门的业务线程池
-
使用
ctx.executor().execute()
将任务放回 EventLoop
public class AsyncBusinessHandler extends SimpleChannelInboundHandler<String> {
private ExecutorService businessThreadPool = Executors.newFixedThreadPool(10);
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
// 提交到业务线程池处理
businessThreadPool.submit(() -> {
// 模拟耗时业务处理
try {
Thread.sleep(1000);
String result = "处理结果: " + msg.toUpperCase();
// 将结果写回EventLoop线程
ctx.executor().execute(() -> {
ctx.writeAndFlush(result);
});
} catch (Exception e) {
ctx.close();
}
});
}
}
3.2 合理使用Promise
public ChannelFuture processAsync(Channel channel, Object input) {
EventLoop eventLoop = channel.eventLoop();
Promise<String> promise = eventLoop.newPromise();
businessThreadPool.execute(() -> {
try {
String result = heavyProcessing(input);
eventLoop.execute(() -> promise.setSuccess(result));
} catch (Exception e) {
eventLoop.execute(() -> promise.setFailure(e));
}
});
return promise;
}
在 ChannelHandler 中: Netty 的 I/O 操作(如 write
, connect
)返回 ChannelFuture
(扩展自 Promise
)。你可以在 ChannelHandler
(如 channelRead
)中发起写操作,获得 ChannelFuture
,然后添加监听器处理写完成事件。
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
// 将消息写回客户端
ChannelFuture writeFuture = ctx.writeAndFlush(msg);
writeFuture.addListener((ChannelFutureListener) future -> {
if (!future.isSuccess()) {
// 处理写失败
future.cause().printStackTrace();
ctx.close();
} else {
// 写成功处理 (可选)
System.out.println("Write successful");
}
});
}
组合/转换操作: 使用 Promise
作为中介点,将一个操作的结果作为输入触发另一个操作。监听器可以基于前一个 Future
的结果设置下一个 Promise
的结果。
3.3 批量异步操作
List<ChannelFuture> futures = new ArrayList<>();
for (int i = 0; i < 100; i++) {
futures.add(channel.write("Message " + i));
}
ChannelFuture lastWriteFuture = channel.writeAndFlush(Unpooled.EMPTY_BUFFER);
futures.add(lastWriteFuture);
// 添加组合监听器
ChannelFuture compositeFuture = new DefaultChannelPromise(channel);
for (ChannelFuture f : futures) {
compositeFuture.addListener(f);
}
3.4 异步超时处理
ChannelFuture future = channel.writeAndFlush("请求数据");
future.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
// 设置超时
channel.eventLoop().schedule(() -> {
if (!future.isDone()) {
future.cancel(true);
channel.close();
}
}, 5, TimeUnit.SECONDS);