Netty 专栏——Netty及其核心组件

https://pyc-ycy.blog.csdn.net/article/details/121875863

Netty 专栏——Netty及其核心组件

一、Netty概述

1、原生NIO的缺点

  • 1)NIO的类库和API库繁杂,使用麻烦,需要熟练掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等
  • 2)需要具备其他额外的技能:Java多线程和Java网络编程,因为NIO涉及到Reactor模式
  • 3)开发工作量和难度非常大:客户端断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常流的处理等
  • 4)JDK NIO的bug:Epoll Bug,会导致Selector空轮询,最终耗尽CPU

2、Netty

在这里插入图片描述
Netty 有JBOSS 提供的一个Java开源框架,提供异步的、基于事件驱动的网络应用程序框架,用以开发高性能、高可靠的网络 IO 程序

二、Netty 高性能架构设计

1、线程模型

1.1、基本介绍

目前存在的线程模型有:传统阻塞I/O服务模型,reactor模式;根据Reactor 的数量和处理资源线程池的数量的不同,有三种典型的实现:单Reactor单线程、单Reactor多线程和主从Reactor多线程。Netty的线程模式主要基于主从Reactor多线程模型做了改进,其中主从Reactor多线程模型有多个Reactor

1.2、Reactor

反应器模式、分发者模式(dispatch)、通知者模式(notifier)

  • 1)基于I/O复用模型:多个连接共用一个阻塞对象,应用程序只需要在一个阻塞对象等待,无需阻塞等待所有连接;当某个连接有新的数据可以处理时,操作系统通知应用程序,线程从阻塞态返回,开始业务处理。
  • 2)基于线程池复用线程资源:不必为每个连接创建线程,将连接完成后的业务处理分配给线程进行处理,一个线程可以处理多个连接的业务。

2、Reactor 模式的核心组成

1)Reactor:reactor 在一个单独的线程中运行,负责监听和分发事件,分发给适当的处理程序来对 IO 事件做出反映
2)Handlers:处理程序执行 I/O 事件要完成的实际事件,执行非阻塞操作

3、单Reactor单线程

在这里插入图片描述

不能充分利用多核CPU的性能,并且无法应对高并发,容易阻塞,此外缺乏可靠性,一旦线程意外终止或死循环,会导致整个通讯模块不可用,不能接收和处理消息,只能用于客户量不大,且业务处理非常快的场景下

4、单Reactor多线程

在这里插入图片描述
Reactor 通过select 监控客户端的连接请求,用dispatch进行分发,Acceptor 通过 accept 处理连接请求,然后创建一个Handler对象处理完成连接后的各种事件,如果是业务处理请求,Reactor 会调用对应的handler,而handler 只负责响应事件,不做具体的业务处理,具体的业务处理又worker线程池中的线程进行,worker线程会在处理完成后的结果返回给handler,handler 再返回给客户端。
可以充分利用多核CPU的处理能力,但多线程数据共享和访问比较复杂,并且Reactor 只有一个线程,面对高并发容易成为应用的性能瓶颈

5、主从 Reactor 多线程

在这里插入图片描述

Rector 子线程和线程池可以有多份。MainReactor和Acceptor共同完成与客户端的连接,连接完成后会被分配给SubReactor,SubReactor将连接加入到连接队列进行监听,并创建相应的handler进行各种事件处理,handler 同样只负责响应,具体业务处理还是由Worker线程池的线程进行处理,worker线程返回处理结果给handler,handler再返回给客户端。
优点:父线程与子线程的数据交互简单职责明确,父线程只需接收新连接,子线程完成后续的业务处理
缺点:编程复杂的较高

6、Netty 的线程模型

在这里插入图片描述

  • 1)Netty抽象出两组线程池,BossGroup 负责接收客户端的连接,WorkerGroup专门负责网络的读写
  • 2)BossGroup和WorkerGroup 类型都是 NIOEventLoopGroup
  • 3)NIOEventLoopGroup 相当于事件循环组,含有多个事件循环,每一个事件循环是 NIOEventLoop
  • 4)NIOEventLoop表示一个不断循环的执行处理任务的线程,每个NIOEventLoop都有一个selector,用于监听绑定在其上的Socket的网络通讯
  • 5)NIOEventLoopGroup 可以有多个线程,可以含有多个NIOEventLoop
  • 6)每个Boss NIOEventLoop 执行步骤有三步:①轮询accept事件、②处理accept事件与client建立连接,生成NIOSocketChannel,并将其注册worker NIOEventLoop上的selector、
    ③处理任务队列的任务,即 runAllTasks
  • 7)每个 worker NIOEventLoop 循环执行的步骤:① 轮询read、write事件 ② 处理 I/O 事件,在NIOSocketChannel处理 ③ 处理任务队列的任务
  • 8)每个 worker NIOEventLoop 处理业务时,会使用 pipeline,pipeline 中包含了 channel,即通过 pipeline 可以获得对应的通道,管道中维护了很多的处理器

二、核心组件

1、Bootstrap 和 ServerBootstrap

1.1、基本概念

Bootstrap或ServerBootstrap 起到一个引导作用,分别用于客户端和服务端,通常通过Bootstrap实例对整个Netty程序进行一些相关配置,如设置BossGroup线程组和workerGroup线程组、channel类型和处理器等。

1.2、常用方法

  • 1)group():在服务端的group方法为 group(parentGroup, childGroup),在客户端的方法为: group(eventGroup) ,用于设置线程组
  • 2)channel() :设置通道类型,服务端通常传参为 NioServerSocketChannel,客户端为 NioSocketChannel
  • 3)option():给 channel 添加配置
  • 4)childOption() :用于给接收到的通道添加配置
  • 5)childHandler():用于设置业务处理类,通常是自定义处理类
  • 6)bind():用于服务端,设置监听端口
  • 7)connect():用于客户端,设置服务端的主机和端口,用于连接服务器

2、Channel

2.1、基本概念

netty 网络通信组件,用于执行网络 I/O 操作,通过其可以获取当前网络连接的状态、配置参数,channel 提供异步的网络 I/O 操作——意味着任何 I/O 调用都会立即返回且不保证调用结束时所请求的 I/O 操作已完成,通常 channel 的 I/O 操作调用会返回一个 channelFuture。channel 支持关联 I/O 操作与对应的处理程序。不同协议、不同阻塞类型的连接有不同的 channel 类型与之对应,常用的 channel 类型见下面

2.2、常用 Channel 类型

  • 1)NioSocketChannel:异步的客户端 TCP Socket 连接
  • 2)NioServerSocketChannel:异步的服务端 TCP Socket 连接
  • 3)NioDatagramChannel:异步的 UDP 连接
  • 4)NioSctpChannel:异步的客户端 Sctp 连接
  • 5)NioSctpServerChannel:异步的服务端 Sctp 连接,这些通道涵盖了 UDP 和 TCP 网络 IO 以及文件 IO。

3、Selector

3.1、基本概念

Netty 基于 Selector 实现 I/O 多路复用,通过一个 selector 线程可以监听多个连接的 Channel 事件。当向一个 Selector 中注册 Channel 后,Selector 内部的机制就可以自动轮询这些注册的 Channel 是否有已就绪的 I/O 事件,从而实现一个线程高效地管理多个 Channel

4、ChannelHandler

4.1、基本概念

ChannelHandler 是一个接口,处理 I/O 事件或拦截 I/O 操作并将其转发到 ChannelPipeline 中的一个处理程序;Channel Handler 本身没有提供很多方法,因为该接口的许多方法需要实现,方便使用期间进行继承和重写,其常用实现类如下:

4.2、常用实现类

  • 1)ChannelInboundHandler:用于处理入站 I/O 事件
  • 2)ChannelOutboundHandler:用于处理出战 I/O 事件
  • 3)ChannelInboundHandlerAdapter:用于处理入站 I/O 事件,可用于自定义处理类进行继承
  • 4)ChannelOutboundHandlerAdapter:用于处理出战 I/O 事件,同样可用于自定义处理类进行继承
  • 5)ChannelDuplexHandler:用于处理入站和出战事件

5、Pipeline 和 ChannelPipeline

  • 1)ChannelPipeline 是一个 Handler 的集合,负责处理和拦截 inbound 或 outbound 的事件和操作,相当于一个贯穿 Netty 的链;ChannelPipeline 实现了一种高级形式的拦截过滤器模式,使用户可以完全控制事件的处理方式,以及 channel 中各个 ChannelHandler 如何相互交互。在 Netty 中每个 Channel 都有且仅有一个 ChannelPipline 与之对应
    在这里插入图片描述

一个channel中包含了一个 ChannelPipeline,而 ChannelPipeline 中维护了一个 ChannelHandlerContext 组成的双向链表,并且每个 ChannelHandlerContext 中关联了一个 ChannelHandler。
入站就是从 head 到 tail 的方向,反之就是出战的方向,两个方向都会各自传递一个 handler 并且互不干扰。

6、ChannelHandlerContext

6.1、基本概念

保存 Channel 相关的所有上下文信息,同时关联一个 ChannelHandler 对象,同时也绑定了对应的 pipeline 和 channel 的信息,方便对 Channel Handler 进行调用

6.2、常用方法

  • 1)ChannelFuture close() :关闭通道
  • 2)ChannelOutboundInvoker flush, 刷新
  • 3)ChannelFuture writeAndFlush(Object msg):将数据写到 ChannelPipeline 中当前的 ChannelHandler 的下一个 ChannelHandler 开始处理

7、ChannelOption

Netty 在创建 Channel 实例后,一般都需要设置 ChannelOption 参数,常用的参数如下

7.1、ChannelOption.SO_BACKLOG

对应 TCP/IP 协议 listen 函数中的 backlog 参数,用于初始化服务器可连接队列的大小。因为服务器是顺序处理客户端的连接请求的,同一时间点只能处理一个请求,后续请求会在一个请求队列中进行等待,而这个队列可以容纳多少个请求就是由 backlog 参数设置的。

7.2、ChannelOption.SO_KEEPALIVE

设置连接保持活跃状态。

8、EventLoopGroup 和 NioEventLoopGroup

NioEventLoopGroup 是 EventLoopGroup 的实现类
EventLoopGroup 是一组 EventLoop 的抽象,每个 EventLoop 都有一个 Selector 实例
EventLoopGroup 提供 next 接口——用于从组里面按照一定规则获取其中一个 EventLoop 来处理任务。在服务端的 BossGroup 和 WorkerGroup 就是 EventLoopGroup 的实例对象。
通常一个服务端口对应一个 Selector 和一个 EventLoop 线程。BossEventLoop 负责接收客户端连接并将 SocketChannel 交给 WorkerEventLoop 进行具体 I/O 处理
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值