Netty核心组件

以下内容输出来源:拉勾教育-Java高薪训练营

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值