Netty核心组件
以下内容输出来源:拉勾教育-Java高薪训练营
Netty核心组件
- 1、bossGroup与WorkerGroup
- 2、Channel
- 3、Selector
- 4、ChannelPipeline与ChannelHandler
- 5、InBound与OutBound
- 6、NioEventLoop
- 7、ServerBootStrap和BootStrap
- 8、如何自定义Handler
1、bossGroup与WorkerGroup
netty抽象出两组线程池,BossGroup
用于接收客户端连接,WorkGroup
用于处理网络读写。两者类型是NioEventLoopGroup(线程池),由NioEventLoop(线程)组成。每个NioEventLoop表示一个不断循环的,执行任务处理的线程,每个NioEventLoop 都有一个Selector与之对应,用于监听绑定在它上面的网络连接,连接事件都是由该线程来处理。
1、每个 Boss NioEventLoop 会监听 Selector 上连接建立的 accept
事件,然后处理 accept 事件与客户端建立网络连接,生成相应的 NioSocketChannel 对象,一个 NioSocketChannel 就表示一条网络连接
。之后会将 NioSocketChannel 注册到某个 Worker NioEventLoop 上的 Selector 中。
2、每个 Worker NioEventLoop 会监听对应 Selector 上的 read/write
事件,当监听到 read/write 事件的时候,会通过 Pipeline
进行处理。一个 Pipeline 与一个 Channel 绑定,在 Pipeline 上可以添加多个 ChannelHandler
,每个 ChannelHandler 中都可以包含一定的逻辑,例如编解码等。Pipeline 在处理请求的时候,会按照我们指定的顺序调用 ChannelHandler。
2、Channel
常用的 NIO Channel 类型包括:
NioSocketChannel:对应异步的 TCP Socket 连接。
NioServerSocketChannel:对应异步的服务器端 TCP Socket 连接。
Channel 主要提供了异步的网络 I/O 操作
,例如:建立连接、读写操作等。I/O 操作返回的是一个 ChannelFuture
对象,我们通过向 ChannelFuture 上注册监听器来监听 I/O 操作的结果。
ChannelFuture表示IO操作的结果,从命名上看就知道是异步的。
// 返回当前正在进行 IO 操作的通道,客户端通过该方法发送连接
Channel channel();
// 等待异步操作执行完毕,服务端通过该方法监听连接请求
ChannelFuture sync();
3、Selector
Selector 是对多路复用器的抽象,也是 Java NIO 的核心基础组件之一。
在 Selector 内部,会通过系统调用不断地查询这些注册在其上的 Channel 是否有已就绪的 I/O 事件,例如,可读事件(OP_READ
)、可写事件(OP_WRITE
)或是网络连接事件(OP_ACCEPT
)等,而无须使用用户线程进行轮询。
4、ChannelPipeline与ChannelHandler
1、ChannelHandler 接口,封装了很多处理事件(连接、读/写)的方法。
//通道就绪事件
public void channelActive(ChannelHandlerContext ctx);
//通道读取数据事件
public void channelRead(ChannelHandlerContext ctx, Object msg);
//数据读取完毕事件
public void channelReadComplete(ChannelHandlerContext ctx);
//通道发生异常事件
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause);
2、 ChannelPipeline 负责处理和拦截InBound与OutBound的事件和操作
// 把一个业务处理类(handler) 添加到链中的第一个位置
ChannelPipeline addFirst(ChannelHandler... handlers);
//把一个业务处理类(handler) 添加到链中的最后一个位置
ChannelPipeline addLast(ChannelHandler... handlers);
3、ChannelHandlerContext 事件处理器的上下文对象
//关闭通道
ChannelFuture close();
//刷新
ChannelOutboundInvoker flush();
//将数据写到 ChannelPipeline 中当前ChannelHandler 的下一个 ChannelHandler 开始处理(出站)
ChannelFuture writeAndFlush(Object msg);
ChannelPipeline 会将一个 ChannelHandler 处理后的数据作为下一个 ChannelHandler 的输入。
ChannelPipeline 中的事件传播主要依赖于ChannelHandlerContext
实现。
ChannelHandlerContext 抽象的是 ChannleHandler 之间的关系以及 ChannelHandler 与ChannelPipeline 之间的关系。
每个ChannelHandlerContext 包含一个具体的ChannelHandler,同时绑定上面的关系,方便对ChannelHandler调用。
综上,一个 Channel 对应一个 ChannelPipeline,一个 ChannelHandlerContext 对应一个ChannelHandler。
最后,需要注意的是,如果要在 ChannelHandler 中执行耗时较长的逻辑,例如,操作 DB 、进行网络或磁盘 I/O 等操作,一般会在注册到 ChannelPipeline 的同时,指定一个线程池异步执行 ChannelHandler 中的操作。
5、InBound与OutBound
Netty 中定义了两种事件类型:入站(Inbound)事件和出站(Outbound)事件。
入站(Inbound)事件一般由 I/O 线程触发。
出站(Outbound)事件与入站(Inbound)事件相反,一般是由用户触发的。
ChannelPipeline 之上可以注册多个 ChannelHandler(ChannelInboundHandler 或 ChannelOutboundHandler),我们通过责任链模式在 ChannelHandler 注册的时候决定处理 I/O 事件的顺序。
Netty 提供的 ChannelInboundHandlerAdapter 和 ChannelOutboundHandlerAdapter 主要是帮助完成事件流转功能的,即自动调用传递事件的相应方法。
6、NioEventLoop
一个 NioEventLoop(线程) 包含了一个 Selector 对象
,可以支持多个 Channel 注册在其上,该 NioEventLoop 可以同时服务多个 Channel,每个 Channel 只能与一个 NioEventLoop 绑定,这样就实现了线程与 Channel 之间的关联。
总之,Channel 中的 I/O 操作是由 ChannelPipeline 中注册的 ChannelHandler 进行处理的,而 ChannelHandler 的逻辑都是由相应 NioEventLoop 的那个线程执行的。
NioEventLoop的主要做三件事,监听 I/O 事件、执行普通任务以及执行定时任务。
1、普通任务
用户产生的普通任务提交到普通任务队列,NioEventLoop发现该任务后立即执行,这是一个多生产者,单消费者
的队列,Netty 使用该队列将外部用户线程产生的任务收集到一起,并在 Reactor 线程内部用单线程的方式串行执行队列中的任务。
2、定时任务
用户将设置的定时任务加入到定时任务队列中,等待对应的NioEventLoop串行执行。
7、ServerBootStrap和BootStrap
分别代表Netty中服务端和客户端的启动助手,通过它完成各种配置。
//该方法用于服务器端, 用来设置两个 EventLoop
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup);
//该方法用来设置一个服务器端的通道实现
public B channel(Class<? extends C> channelClass);
//用来给 ServerChannel 添加配置
public <T> B option(ChannelOption<T> option, T value);
//用来给接收到的通道添加配置
public <T> ServerBootstrap childOption(ChannelOption<T> childOption, T value);
//该方法用来设置业务处理类(自定义的 handler)
public ServerBootstrap childHandler(ChannelHandler childHandler);
//该方法用于服务器端, 用来设置占用的端口号
public ChannelFuture bind(int inetPort);
//该方法用于客户端, 用来设置一个 EventLoop
public B group(EventLoopGroup group);
//该方法用于客户端, 用来连接服务器端
public ChannelFuture connect(String inetHost, int inetPort);
8、如何自定义Handler
实现ChannelHandler
接口或者实现ChannelInBoundHandlerAdapter
还没有评论,来说两句吧...