EventLoop
EventLoop继承自
EventExecutor,
EventLoopGroup。从这点可以看出
EventLoop首先是一个Executor,任务执行器。
再者它本身是一个环,能够负载均衡执行压力。可以说EventLoop是Netty4的一个核心,整个Netty4的运转都是围绕着它。
一、认识EventLoop有哪些方法(下面列举的是一些比较典型的)
EventLoop next()
Future<?> submit(Runnable task)
ChannelFuture register(Channel channel)
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
Future<?> shutdownGracefully()
从这些方法,我们可以清晰的认识到EventLoop可以实现以下功能:
引用
1. 执行任务(IO/非IO任务)
2. 将Channel绑定到EventLoop上
3. 执行定时任务
4. 关闭任务
二、SingleThreadEventLoop & NioEventLoop - EventLoop的2个关键实现
SingleThreadEventLoop继承自
SingleThreadEventExecutor这是一个标准的线程池的实现。和JDK中线程池的实现大同小异。主要的用处就是执行任务。
NioEventLoop继承自
SingleThreadEventLoop也就是说他具备执行任务的能力。但是它更重要的是每个
NioEventLoop里面包含一个Selector,也就是说
它具备网络处理能力。我们来看看它是如何工作的。
启动时打开一个Selector
从下面代码可以看到,Channel是这样绑定到NioEventLoop上的
protected void doRegister() throws Exception {
boolean selected = false;
for (;;) {
try {
selectionKey = javaChannel().register(eventLoop().selector, 0, this);
return;
} catch (CancelledKeyException e) {
if (!selected) {
// Force the Selector to select now as the "canceled" SelectionKey may still be
// cached and not removed because no Select.select(..) operation was called yet.
eventLoop().selectNow();
selected = true;
} else {
// We forced a select operation on the selector before but the SelectionKey is still cached
// for whatever reason. JDK bug ?
throw e;
}
}
}
}
从下面代码看到NioEventLoop做的事情就是处理各种NIO事件
@Override
protected void run() {
for (;;) {
oldWakenUp = wakenUp.getAndSet(false);
try {
if (hasTasks()) {
selectNow();
} else {
select();
if (wakenUp.get()) {
selector.wakeup();
}
}
cancelledKeys = 0;
final long ioStartTime = System.nanoTime();
needsToSelectAgain = false;
if (selectedKeys != null) {
processSelectedKeysOptimized(selectedKeys.flip());
} else {
processSelectedKeysPlain(selector.selectedKeys());
}
final long ioTime = System.nanoTime() - ioStartTime;
final int ioRatio = this.ioRatio;
runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
if (isShuttingDown()) {
closeAll();
if (confirmShutdown()) {
break;
}
}
} catch (Throwable t) {
logger.warn("Unexpected exception in the selector loop.", t);
// Prevent possible consecutive immediate failures that lead to
// excessive CPU consumption.
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// Ignore.
}
}
}
}
private static void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
final NioUnsafe unsafe = ch.unsafe();
if (!k.isValid()) {
// close the channel if the key is not valid anymore
unsafe.close(unsafe.voidPromise());
return;
}
try {
int readyOps = k.readyOps();
// Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead
// to a spin loop
if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
unsafe.read();
if (!ch.isOpen()) {
// Connection already closed - no need to handle write.
return;
}
}
if ((readyOps & SelectionKey.OP_WRITE) != 0) {
// Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write
ch.unsafe().forceFlush();
}
if ((readyOps & SelectionKey.OP_CONNECT) != 0) {
// remove OP_CONNECT as otherwise Selector.select(..) will always return without blocking
// See https://github.com/netty/netty/issues/924
int ops = k.interestOps();
ops &= ~SelectionKey.OP_CONNECT;
k.interestOps(ops);
unsafe.finishConnect();
}
} catch (CancelledKeyException e) {
unsafe.close(unsafe.voidPromise());
}
}
Read操作最终会当作一个定时任务添加到NioEventLoop中被执行
public ChannelHandlerContext read() {
final DefaultChannelHandlerContext next = findContextOutbound();
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
next.invokeRead();
} else {
Runnable task = next.invokeReadTask;
if (task == null) {
next.invokeReadTask = task = new Runnable() {
@Override
public void run() {
next.invokeRead();
}
};
}
executor.execute(task);
}
return this;
}
同样的Write操作会当作一个定时任务添加到NioEventLoop中被执行
private void write(Object msg, boolean flush, ChannelPromise promise) {
DefaultChannelHandlerContext next = findContextOutbound();
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
next.invokeWrite(msg, promise);
if (flush) {
next.invokeFlush();
}
} else {
int size = channel.estimatorHandle().size(msg);
if (size > 0) {
ChannelOutboundBuffer buffer = channel.unsafe().outboundBuffer();
// Check for null as it may be set to null if the channel is closed already
if (buffer != null) {
buffer.incrementPendingOutboundBytes(size);
}
}
safeExecute(executor, WriteTask.newInstance(next, msg, size, flush, promise), promise, msg);
}
}
总结:
- NioEventLoop是Netty4最基础的一个东西
- 在Netty4里面一切操作都是在NioEventLoop中被执行
- NioEventLoop既能执行IO任务,也能执行非IO任务,它可以被Channel绑定,处理Channel中IO事物,也可以用来向它提交任务,当作一个任务管理器使用
分享到:
相关推荐
EventLoopGroup是EventLoop的集合,通常有老板线程组和工作线程组之分,老板线程负责接受新的连接,然后分配给工作线程处理。 **ByteBuf容器** ByteBuf是Netty提供的字节缓冲区,它是Java NIO ByteBuffer的一个...
Netty线程模型和EventLoop线程模型概述EventLoop事件循环任务调度JDK任务调度EventLoop任务调度线程管理线程分配非阻塞传输阻塞传输N
本书首先会介绍Netty的基本概念,包括其非阻塞I/O模型、事件驱动架构以及Channel、EventLoop、Buffer等核心组件。接着,通过一系列逐步进阶的案例,如构建简单的Echo服务器、处理HTTP请求、实现WebSocket通信,读者...
在Netty中,`NioEventLoopGroup`扮演着Reactor的角色,其中`NioEventLoop`实现了`EventLoop`接口,负责处理各种I/O事件。此外,`Bootstrap`和`ServerBootstrap`类分别用于客户端和服务端的启动配置。 #### 三、缓冲...
这个“netty4 api 中文”压缩包包含的是Netty 4.1版本的中文API文档,对于Java开发者来说,是学习和使用Netty的重要参考资料。 Netty 的核心设计理念是基于Reactor模式,这种模式在处理并发I/O操作时能显著提高效率...
6. **EventLoop 和 EventLoopGroup**: EventLoop 是执行事件处理的线程,EventLoopGroup 是 EventLoop 的集合。这种设计允许 Netty 在多线程环境下高效地处理并发连接。 7. **Future 和 Promise**: Netty 提供了 ...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。在本文中,我们将深入浅出地探讨 Netty 实现的 HTTP 协议栈,并通过实践来理解其工作原理。 首先,我们要...
本书首先介绍了Netty的基本架构,包括它的Channel、EventLoop、Bootstrap、Pipeline等核心组件。Channel是Netty中处理网络通信的基本单元,可以理解为一个连接;EventLoop是负责处理I/O事件的线程,确保了高效的事件...
ChannelHandlerAdapter 4.X版本和5.X版本的差别很大。ChannelRead是属于5.X版本的4.X版本没有这个方法,所以如果要用ChannelRead。可以更换5.X版本的Netty。
1. **EventLoopGroup**:Netty 中的 EventLoopGroup 是一组事件循环(EventLoop)的集合,每个事件循环对应一个独立的工作线程。在服务器端,通常会创建两个 EventLoopGroup,一个用于接收客户端连接(BossGroup),...
Java进阶技术-netty进阶之路
这个“netty4 sources 源码”指的是Netty 4.x 版本的源代码,其中4.0.33.Final是特定的版本号。源码分析对于理解Netty的工作原理、优化性能以及定制化开发非常有帮助。 Netty 的核心特性包括: 1. **异步事件驱动*...
赠送jar包:transport-netty4-client-5.5.1.jar; 赠送原API文档:transport-netty4-client-5.5.1-javadoc.jar; 赠送源代码:transport-netty4-client-5.5.1-sources.jar; 赠送Maven依赖信息文件:transport-netty...
4. **异常处理**:定义异常处理器,捕获并处理可能出现的网络异常,如连接断开、超时等。 5. **数据处理**:根据业务需求,解析接收到的数据并进行相应的业务逻辑处理,如存储数据、触发报警、执行远程控制等。 6....
【描述】:“第 5 章Netty 高性能之道第 6 章揭开 BootStrap 的神秘面纱第 7 章大名鼎鼎的 EventLoop第 8 章Netty 大动脉 Pipeline” 【标签】:“” 【部分内容】:“咕泡出品,必属精品 www.gupaoedu.com1第 3 ...
Netty进阶之路 跟着案例学Netty 整本书无密码,Netty进阶之路 跟着案例学Netty
4. **EventLoop**:探索事件循环的调度机制,如何平衡负载和处理并发请求。 5. **编码解码器**:如 LengthFieldBasedFrameDecoder 和 StringDecoder,它们是如何将原始字节流转换为应用程序可用的数据对象的。 6. **...
这意味着在 Netty 中,I/O 操作不会阻塞线程,而是通过事件循环(EventLoop)和事件处理器(ChannelHandler)来处理。当 I/O 操作完成时,相应的事件会被触发,然后由事件处理器进行处理,这样极大地提高了系统性能...
赠送jar包:transport-netty4-client-6.3.0.jar; 赠送原API文档:transport-netty4-client-6.3.0-javadoc.jar; 赠送源代码:transport-netty4-client-6.3.0-sources.jar; 赠送Maven依赖信息文件:transport-netty...
4. **ChannelHandler 配置**: ChannelHandler 是 Netty 中处理网络事件的核心组件。在 Spring 集成中,可以创建一个 ChannelHandlerContext 的工厂类,该工厂由 Spring 管理,并在需要时为每个新建的 Channel 提供 ...