文章目录
- Netty简介
- Netty结构
- Netty线程模型
- 服务端线程模型
- 客户端线程模型
- NioEventLoop
- Task
- Netty中的Channel
- 工作原理
- 线程
- ChannelPipeline和ChannelHandler
- ChannelHandlerContext
- ChannelHandler
Netty简介
Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
换句话说,Netty是一个NIO框架,使用它可以简单快速地开发网络应用程序,比如客户端和服务端的协议。Netty大大简化了网络程序的开发过程比如TCP和UDP的 Socket的开发。
Netty结构
NioEventLoop采用串行化设计理念:
NioEventLoop线程池中有若干个NioEventLoop线程,每一个NioEventLoop线程串行执行Handler链;每当有一个客户端接入,从线程池中获取一个可用的NioEventLoop线程,当数组到达上限之后,从0开始(负载均衡);每个客户端连接一个线程,这样保证了数据的安全性(避免多个线程同时访问)
Netty线程模型
- Acceptor中的NioEventLoop用于接收TCP连接,初始化参数
- I/O线程池中的NioEventLoop异步读取通信对端的数据报,发送读事件到channel
- 异步发送消息到对端,调用channel的消息发送接口
- 执行系统调用Task
- 执行定时Task
服务端线程模型
一种比较流行的做法是服务端监听线程和IO线程分离,类似于Reactor的多线程模型,它的工作原理图如下:
客户端线程模型
NioEventLoop
NioEventLoop是Netty的Reactor线程,它在Netty Reactor线程模型中的职责如下:
- 作为服务端Acceptor线程,负责处理客户端的请求接入
- 作为客户端Connecor线程,负责注册监听连接操作位,用于判断异步连接结果
- 作为IO线程,监听网络读操作位,负责从SocketChannel中读取报文
- 作为IO线程,负责向SocketChannel写入报文发送给对方,如果发生写半包,会自动注册监听写事件,用于后续继续发送半包数据,直到数据全部发送完成
如下图,是一个NioEventLoop的处理链:
- 处理链中的处理方法是串行化执行的
- 一个客户端连接只注册到一个NioEventLoop上,避免了多个IO线程并发操作
Task
Netty Reactor线程模型中有两种Task:系统Task和定时Task
- 系统Task:创建它们的主要原因是,当IO线程和用户线程都在操作同一个资源时,为了防止并发操作时锁的竞争问题,将用户线程封装为一个Task,在IO线程负责执行,实现局部无锁化
- 定时Task:主要用于监控和检查等定时动作
基于以上原因,NioEventLoop不是一个纯粹的IO线程,它还会负责用户线程的调度
参考:
IO多路复用之select、poll、epoll详解:
Netty中的Channel
Channel是Netty的核心概念之一,它是Netty网络通信的主体,由它负责同对端进行网络通信、注册和数据操作等功能。
工作原理
如上图所示:
1.一旦用户端连接成功,将新建一个channel同该用户端进行绑定
2.channel从EventLoopGroup获得一个EventLoop,并注册到该EventLoop,channel生命周期内都和该EventLoop在一起(注册时获得selectionKey)
3.channel同用户端进行网络连接、关闭和读写,生成相对应的event(改变selectinKey信息),触发eventloop调度线程进行执行
4.如果是读事件,执行线程调度pipeline来处理用户业务逻辑
线程
多个channel可以注册到一个eventloop上,所有的操作都是顺序执行的,eventloop会依据channel的事件调用channel的方法进行相关操作,每个channel的操作和处理在eventloop中都是顺序的,如下图:
ChannelPipeline和ChannelHandler
ChannelPipeline和ChannelHandler用于channel事件的拦截和处理,Netty使用类似责任链的模式来设计ChannelPipeline和ChannelHandler
ChannelPipeline相当于ChannelHandler的容器,channel事件消息在ChannelPipeline中流动和传播,相应的事件能够被ChannelHandler拦截处理、传递、忽略或者终止,如下图所示:
ChannelHandlerContext
每个ChannelHandler 被添加到ChannelPipeline 后,都会创建一个ChannelHandlerContext 并与之创建的ChannelHandler 关联绑定。如下图:
ChannelHandler通过ChannelHandlerContext来操作channel和channelpipeline
ChannelHandler
ChannelHandler负责I/O事件或者I/O操作进行拦截和处理,用户可以通过ChannelHandlerAdapter来选择性的实现自己感兴趣的事件拦截和处理。
由于Channel只负责实际的I/O操作,因此数据的编解码和实际处理都需要通过ChannelHandler进行处理。
注:
ChannelPipeline是线程安全的,多个业务线程可以并发的操作ChannelPipeline;ChannelHandler不是线程安全的,用户需要自己保重ChannelHandler的线程安全