前面我们分析了Pipeline,还有一个东西值得我们去研究研究,那就是EventLoop。哈哈!我们继续吧!
不管是在客户端还是服务端,在netty启动的时候,都会指定EventLoopGroup,当然用的最多的就是NIO,所以都会指定NioEventLoopGroup。那么这个NioEventLoopGroup在Nnetty中是扮演什么角色的喃!netty是基于Reactor模型的一个实现,那么我们先简单的说明一下Reactor的线程模型。
单线程模型:
所有的acceptor处理和handler处理都在同一个线程中。这种模式的坏处就是显而易见的了,当一个handler阻塞时,会导致所有的handler都不能执行,同时整个服务也不会接受新请求。
多线程模型:
与单线程模型的区别在于,把acceptor让一个独立的线程来处理,后面有一组NIO的线程池来处理客户端连接的IO操作。
特点:
有一个专门的acceptor线程用于监听客户端的TCP连接请求。
客户端连接的IO操作由一个特定的NIO线程池负责. 每个客户端连接都与一个特定的NIO线程绑定, 因此在这个客户端连接中的所有IO操作都是在同一个线程中完成的.
客户端连接有很多,但是NIO线程池中的线程数是较少的,因此一个NIO线程可以同时绑定到多个客户端连接中。
为什么不让一个特定的线程池来处理acceptor喃???
单线程对应在netty中的表现是什么样子的喃
看一个例子:
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup)
.channel(NioServerSocketChannel.class)
........
NioEventLoopGroup构造参数是1,表明线程池的大小是1,接着调用ServerBootstrap的group(bossGroup)方法。接着我们看看ServerBootstrap的group(bossGroup)方法的实现:
public ServerBootstrap group(EventLoopGroup group) {
return group(group, group);
}
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
super.group(parentGroup);
if (childGroup == null) {
throw new NullPointerException("childGroup");
}
if (this.childGroup != null) {
throw new IllegalStateException("childGroup set already");
}
this.childGroup = childGroup;
return this;
}
很容易我们看出来了,传入一个group的时候,我们的bossGroup和workerGroup是同一个NioEventLoopGroup。并且这个NioEventLoopGroup只有一个线程,这样acceptor和后续的所有客户端连接的IO操作都在这个线程里面了,这个就是对应Reactor的单线程模型。
再看一个例子:
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
........
bossGroup只有一个线程,workerGroup的线程是CPU核心数乘以2。这样就是Reactor的多线程模式。
下面来看看NioEventLoopGroup和NioEventLoop初始化过程:
1,NioEventLoopGroup内部维护一个类型为EventExecutor数组(变量:children),构造了一个线程池
2,调用newChild抽象方法来初始化children数组
3,抽象方法newChild在 NioEventLoopGroup 中实现的,返回一个NioEventLoop实例
NioEventLoop:
继承关系:NioEventLoop-->SingleThreadEventLoop-->SingleThreadEventExecutor-->AbstractScheduledEventExecutor。
SingleThreadEventExecutor是netty中对本地线程的抽象,它内部有一个Thread thread属性, 存储了一个本地Java线程。一个NioEventLoop和一个线程绑定.
在AbstractScheduledEventExecutor中,实现了schedule的功能,我们可以通过调用NioEventLoop实例的schedule方法来运行一些定时任务。
在SingleThreadEventLoop中实现了任务队列的功能,我们可以通过调用NioEventLoop实例的execute方法来向任务队列中添加一个task,由NioEventLoop进行调度执行。
NioEventLoop肩负着两种任务:第一作为IO线程,执行与channel的IO操作,包括调用select等待就绪的IO事件,读写数据,数据的处理。第二作为任务队列,执行队列中的任务
关于channel和EventLoop是怎么关联起来的可以看看
http://jishuaige.iteye.com/blog/2356798---netty探索之旅三
EventLoop的启动
NioEventLoop的启动,其实就是NioEventLoop所绑定的本地Java线程的启动。
在NioEventLoop的父类SingleThreadEventExecutor中
private void startThread() {
if (STATE_UPDATER.get(this) == ST_NOT_STARTED) {
if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
thread.start();
}
}
}
这个方法调用NioEventLoop所绑定的本地Java线程的start方法,启动线程。
跟着这个方法被调用轨迹走:SingleThreadEventExecutor中的execute
public void execute(Runnable task) {
if (task == null) {
throw new NullPointerException("task");
}
boolean inEventLoop = inEventLoop();
if (inEventLoop) {
addTask(task);
} else {
startThread();
addTask(task);
if (isShutdown() && removeTask(task)) {
reject();
}
}
if (!addTaskWakesUp && wakesUpForTask(task)) {
wakeup(inEventLoop);
}
}
在第三节我们分析channel注册的时候,在AbstractUnsafe.register有这段代码:
if (eventLoop.inEventLoop()) {
register0(promise);
} else {
try {
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
.....................
eventLoop.execute就是在调用上面的SingleThreadEventExecutor.execute,这样NioEventLoop所对应的线程就启动了。
当EventLoop.execute第一次被调用时,就会触发startThread()的调用,进而EventLoop所对应的Java线程的启动。
- 大小: 28.8 KB
分享到:
相关推荐
Java进阶技术-netty进阶之路
《Netty进阶之路-跟着案例学Netty》是由知名技术专家李林峰撰写的一本专为Java开发者深入理解Netty框架而准备的书籍。这本书旨在通过实例教学,帮助读者全面掌握Netty的核心特性和实战技巧,提升网络编程的能力。 ...
Netty进阶之路 跟着案例学Netty 整本书无密码,Netty进阶之路 跟着案例学Netty
《Netty进阶之路:跟着案例学Netty》中的案例涵盖了Netty的启动和停止、内存、并发多线程、性能、可靠性、安全等方面,囊括了Netty绝大多数常用的功能及容易让人犯错的地方。在案例的分析过程中,还穿插讲解了Netty...
精选自1000多个一线业务实际案例,从原理到实践全景式讲解Netty项目实践,快速领悟Netty专家花大量时间积累的经验,提高编程水平及分析解决问题的能力,《Netty木又威指南》作者力作,众专家力荐 Netty将Java NIO...
Netty学习之ServerChannel Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。在本篇中,我们将深入探讨ServerChannel这一核心概念,它是Netty中用于接收客户端...
读书笔记:Netty权威指南学习之旅
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。在本文中,我们将深入探讨Netty的基本概念,通过“Hello World”范例来理解其工作原理。 首先,让我们理解...
在《Netty进阶之路:跟着案例学Netty》中,作者将在过去几年实践中遇到的问题,以及Netty学习者咨询的相关问题,进行了归纳和总结,以问题案例做牵引,通过对案例进行剖析,讲解问题背后的原理,并结合Netty源码分析...
Netty基础,用于学习Netty,参考黑马程序员的netty教程
7. **Netty底层原理**:探讨Netty如何利用Java NIO实现异步非阻塞I/O,以及零拷贝技术的工作机制,帮助读者理解Netty的高效性。 8. **案例分析**:通过实际项目案例,展示Netty在实际场景中的应用,如P2P下载、...
《Netty实战》这本书是针对Java网络编程框架Netty的一本深入实践教程,旨在帮助读者掌握Netty的核心特性和实际应用。Netty是一款高性能、异步事件驱动的网络应用程序框架,广泛应用于各种分布式系统、微服务架构以及...
7. **心跳机制**:Netty提供了心跳包处理,用于检测连接的活跃状态,防止连接长时间无交互导致的失效。 8. **异常处理**:Netty提供了一套完整的异常处理机制,使得在发生错误时能够优雅地恢复或关闭连接。 9. **...
ChannelHandlerAdapter 4.X版本和5.X版本的差别很大。ChannelRead是属于5.X版本的4.X版本没有这个方法,所以如果要用ChannelRead。可以更换5.X版本的Netty。
**Netty 深度解析** Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。它广泛应用于各种领域,如分布式系统、云计算、游戏服务器、大数据传输等。Netty 的设计...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。在本文中,我们将深入探讨 Netty 实时通讯的原理与应用,以及如何利用它构建 WebSocket 服务。 WebSocket 是...
netty-socketio-netty-socketio-2.0.6 ,Socket.IO 是一个库,可以在客户端和服务器之间实现低延迟, 双向和基于事件的通信:netty-socketio-netty-socketio-2.0.6.tar.gznetty-socketio-netty-socketio-2.0.6.zip
在Netty中,最重要的概念之一是“Boss线程”和“Worker线程”的模型。Boss线程负责接收新的连接请求,而Worker线程则处理这些连接后的读写操作,这种模型能够有效提高系统的并发能力。Netty的NIO(非阻塞I/O)模型...
netty案例,netty4.1中级拓展篇七《Netty请求响应同步通信》源码 https://mp.weixin.qq.com/s?__biz=MzIxMDAwMDAxMw==&mid=2650724835&idx=1&sn=93fc37b8c35b19f91ef246632a37bab9&scene=19#wechat_redirect
Netty是Java领域的一款高性能、异步事件驱动的网络应用框架,主要用于快速开发可维护的高性能协议服务器和客户端。在本精讲中,我们将深入探讨Netty的核心概念、设计模式以及实际应用场景,帮助你全面理解并掌握...