事件驱动是一种编程范式,系统通过监听和响应事件(Event)来执行操作,而不是通过轮询或阻塞等待。事件通常由外部刺激触发(如网络 I/O、定时器、用户任务),由事件循环(Event Loop)捕获并分发给相应的处理逻辑。事件驱动的核心优势是:
Netty 的事件驱动模型基于 Java NIO 的多路复用机制(Selector),结合其自定义的事件循环(EventLoop)和管道(ChannelPipeline),实现高效的事件生产、传播和处理。Netty 的事件驱动包括:
Netty 的事件驱动依赖以下组件:
以下从事件的生产、传播和处理三个阶段,详细解析 Netty 如何实现事件驱动。
事件的生产主要由 EventLoop 和 Channel 负责,涉及底层 I/O 事件、通道状态变化和用户任务。
机制:
实现类:
源码分析(NioEventLoop.run):
@Override
protected void run() {
for (;;) {
try {
switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
case SelectStrategy.CONTINUE:
continue;
case SelectStrategy.BUSY_WAIT:
// fall-through to SELECT since the busy-wait is not supported with NIO
case SelectStrategy.SELECT:
select(wakenUp.getAndSet(false));
if (wakenUp.get()) {
selector.wakeup();
}
// fall through
default:
}
cancelledKeys = 0;
needsToSelectAgain = false;
final int ioRatio = this.ioRatio;
if (ioRatio == 100) {
try {
processSelectedKeys();
} finally {
runAllTasks();
}
} else {
final long ioStartTime = System.nanoTime();
try {
processSelectedKeys();
} finally {
final long ioTime = System.nanoTime() - ioStartTime;
runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
}
}
} catch (Throwable t) {
handleLoopException(t);
}
try {
if (isShuttingDown()) {
closeAll();
if (confirmShutdown()) {
return;
}
}
} catch (Throwable t) {
handleLoopException(t);
}
}
}
机制:
典型事件:
源码分析(NioSocketChannel.doFinishConnect):
private void doFinishConnect() throws Exception {
if (!javaChannel().finishConnect()) {
throw new Error();
}
pipeline().fireChannelActive();
}
机制:
源码分析(SingleThreadEventLoop.schedule):
@Override
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
ObjectUtil.checkNotNull(command, "command");
ObjectUtil.checkNotNull(unit, "unit");
if (delay < 0) {
delay = 0;
}
validateScheduled(delay, unit);
return schedule(new ScheduledFutureTask<Void>(this, command, null, ScheduledFutureTask.deadlineNanos(unit.toNanos(delay))));
}
事件的传播由 ChannelPipeline 负责,通过链式调用将事件分发给 ChannelHandler。
定义:
功能:
源码分析(DefaultChannelPipeline.fireChannelRead):
@Override
public final ChannelPipeline fireChannelRead(Object msg) {
AbstractChannelHandlerContext.invokeChannelRead(head, msg);
return this;
}
static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) {
final Object m = next.pipeline().touch(ObjectUtil.checkNotNull(msg, "msg"), next);
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
next.invokeChannelRead(m);
} else {
executor.execute(() -> next.invokeChannelRead(m));
}
}
入站事件:
出站事件:
源码分析(AbstractChannelHandlerContext.invokeChannelRead):
private void invokeChannelRead(Object msg) {
if (invokeHandler()) {
try {
((ChannelInboundHandler) handler()).channelRead(this, msg);
} catch (Throwable t) {
notifyHandlerException(t);
}
} else {
fireChannelRead(msg);
}
}
事件的处理由 ChannelHandler 负责,用户通过实现 ChannelInboundHandler 或 ChannelOutboundHandler 定义具体逻辑。
ChannelInboundHandler:
处理入站事件,如 channelRead、channelActive、exceptionCaught。
接口定义:
public interface ChannelInboundHandler extends ChannelHandler {
void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception;
void channelActive(ChannelHandlerContext ctx) throws Exception;
void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;
// 其他方法
}
ChannelOutboundHandler:
处理出站事件,如 write、connect、close。
接口定义:
public interface ChannelOutboundHandler extends ChannelHandler {
void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception;
void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) throws Exception;
// 其他方法
}
SimpleChannelInboundHandler:
简化实现,自动释放消息资源。
示例:
public class SimpleChannelInboundHandler<I> extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
boolean release = true;
try {
if (acceptInboundMessage(msg)) {
@SuppressWarnings("unchecked")
I imsg = (I) msg;
channelRead0(ctx, imsg);
} else {
release = false;
ctx.fireChannelRead(msg);
}
} finally {
if (release) {
ReferenceCountUtil.release(msg);
}
}
}
protected void channelRead0(ChannelHandlerContext ctx, I msg) throws Exception {
// 由子类实现
}
}
入站事件处理:
出站事件处理:
源码分析(DefaultChannelHandlerContext.write):
@Override
public ChannelFuture write(final Object msg, final ChannelPromise promise) {
if (msg == null) {
throw new NullPointerException("msg");
}
try {
if (isNotValidPromise(promise, true)) {
ReferenceCountUtil.release(msg);
return promise;
}
} catch (RuntimeException e) {
ReferenceCountUtil.release(msg);
throw e;
}
write(msg, false, promise);
return promise;
}
private void write(Object msg, boolean flush, ChannelPromise promise) {
AbstractChannelHandlerContext next = findContextOutbound();
final Object m = pipeline.touch(msg, next);
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
if (flush) {
next.invokeWriteAndFlush(m, promise);
} else {
next.invokeWrite(m, promise);
}
} else {
AbstractWriteTask task;
if (flush) {
task = WriteAndFlushTask.newInstance(next, m, promise);
} else {
task = WriteTask.newInstance(next, m, promise);
}
safeExecute(executor, task, promise, m);
}
}
用户事件:
通过 ctx.fireUserEventTriggered(event) 触发自定义事件。
示例:
ctx.fireUserEventTriggered(new CustomEvent("User event"));
定时任务:
通过 EventLoop.schedule 安排定时任务。
示例:
channel.eventLoop().schedule(() -> {
System.out.println("Scheduled task executed");
}, 1, TimeUnit.SECONDS);
协作:
示例:
源码分析(NioByteUnsafe.read):
@Override
public final void read() {
final ChannelConfig config = config();
final ChannelPipeline pipeline = pipeline();
final ByteBufAllocator allocator = config.getAllocator();
final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle();
allocHandle.reset(config);
ByteBuf byteBuf = null;
boolean close = false;
try {
do {
byteBuf = allocHandle.allocate(allocator);
allocHandle.lastBytesRead(doReadBytes(byteBuf));
if (allocHandle.lastBytesRead() <= 0) {
byteBuf.release();
byteBuf = null;
close = allocHandle.lastBytesRead() < 0;
break;
}
allocHandle.incMessagesRead(1);
pipeline.fireChannelRead(byteBuf);
byteBuf = null;
} while (allocHandle.continueReading());
allocHandle.readComplete();
pipeline.fireChannelReadComplete();
} catch (Throwable t) {
handleReadException(pipeline, byteBuf, t, close, allocHandle);
}
}
协作:
示例:
源码分析(ChannelHandlerContext.fireChannelRead):
@Override
public ChannelHandlerContext fireChannelRead(final Object msg) {
invokeChannelRead(findContextInbound(), msg);
return this;
}
协作:
示例:
源码分析(DefaultChannelPromise.notifyListeners):
private void notifyListeners() {
Object listeners = this.listeners;
if (listeners == null) {
return;
}
EventExecutor executor = this.executor();
if (executor.inEventLoop()) {
notifyListenersNow();
} else {
executor.execute(this::notifyListenersNow);
}
}
以下通过客户端和服务器示例,展示 Netty 事件驱动的实际应用。
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
public class NettyServer {
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) {
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new StringEncoder());
ch.pipeline().addLast(new SimpleChannelInboundHandler<String>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
System.out.println("Received: " + msg);
ctx.writeAndFlush("Hello: " + msg);
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
System.out.println("Client connected");
ctx.fireChannelActive();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
});
}
});
ChannelFuture f = b.bind(8080).sync();
f.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
public class NettyClient {
public static void main(String[] args) throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) {
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new StringEncoder());
ch.pipeline().addLast(new SimpleChannelInboundHandler<String>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
System.out.println("Received: " + msg);
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
ctx.writeAndFlush("ClientHello");
}
});
}
});
ChannelFuture f = b.connect("localhost", 8080).sync();
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
}
}
Netty 的事件驱动模型通过 EventLoop、ChannelPipeline 和 ChannelHandler 的协作实现了高效的网络 I/O 和事件处理。其核心机制包括: