netty入门介绍及应用实例

Netty介绍及使用

1. Netty介绍

1.1 简介

Netty是由JBOSS提供的一个java开源框架,现为Github上的独立项目。Netty是一个异步的基于事件驱动的网络应用框架,用以快速开发高性能、高可靠的网络IO程序。Netty主要针对在TCP协议下,面向Clients端的高并发应用,或Peer-to-Peer场景下的大量数据持续传输的应用。Netty本质是NIO框架,适用于服务器通讯相关的多种应用场景。

要透彻理解Netty,先学习NIO java NIO介绍及入门案例

NIO的类库和API繁杂,使用麻烦;开发工作量和难度都非常大,JDK NIO的selector空轮询问题,Netty基于NIO进行了封装

1.2 应用场景

  • 互联网行业: 在分布式系统中,各个节点之间需要远程服务调用,高性能的 RPC 框架必不可少,Netty 作为异步高性能的通信框架,往往作为基础通信组件被这些 RPC 框架使用。典型的有阿里的Dubbo
  • 游戏行业: Netty 作为高性能的基础通信组件,提供了 TCP/UDP 和 HTTP 协议栈,方便定制和开发私有协议栈,账号登录服务器;地图服务器之间可以方便的通过 Netty 进行高性能的通信
  • 大数据领域: Hadoop 的高性能通信和序列化组件 Avro 的 RPC 框架,默认采用 Netty 进行跨节点通信,它的 Netty Service 基于 Netty 框架二次封装实现。

1.3 优点

  1. 设计优雅:适用于各种传输类型的统一API阻塞和非阻塞Socket;基于灵活且可扩展的事件模型,可以清晰地分离关注点;高度可定制的线程模型-单线程、一个或多个线程池
  2. 使用方便:详细记录的Javadoc,用户指南和示例;没有其它依赖项
  3. 高性能、吞吐量更高;延迟更低;减少资源消耗;最小化不必要的内存复制
  4. 安全:完整的SSL/TLS和StartTLS支持
  5. 社区活跃、不断更新,版本迭代周期短

2. Netty高性能架构设计

2.1 Reactor模式(线程模型)介绍

Reactor模式中核心组成:

  • Reactor: Reactor在一个单独的线程中运行,负责监听和分发事件,分发给适当的处理程序来对IO事件做出反应
  • Handlers: 处理程序执行I/O事件要完成实际的事件。Reactor通过调度适当的处理程序来响应I/O事件,处理程序执行非阻塞操作

Reactor模式分类:

  • 单Reactor单线程:

在这里插入图片描述

  1. select可以实现应用程序通过一个阻塞对象监听多路复用连接请求

  2. Reactor对象通过selector监控客户端请求事件,收到事件后通过Dispatch进行分发

  3. 如果是建立连接请求事件,则由Acceptor通过accept处理连接请求,然后创建一个Handler对象处理连接完成后的后续业务处理

  4. 如果不是建立连接事件,则Reactor会分发调用连接对应的Handler来响应

  5. Handler会完成Read->业务处理->Send的完整业务流程

优缺点:

  • ​ 优点:模型简单,没有多线程、进程通讯、竞争问题,全部都在一个线程中完成

  • ​ 缺点:性能问题,只有一个线程,无法完全发挥多核CPU的性能。Handler在处理某个连接上的业务时,整个进程无法处理其它连接事件,很容易导致性能瓶颈;可靠性问题,线程性问题,线程意外终止,或者进入死循环,会导致整个系统通信模块不可用,不能接收和处理外部消息,造成节点故障

    NIO就属于这种模型

  • 单Reactor多线程

在这里插入图片描述

  1. select可以实现应用程序通过一个阻塞对象监听多路复用连接请求

  2. Reactor对象通过selector监控客户端请求事件,收到事件后通过Dispatch进行分发

  3. 如果是建立连接请求事件,则由Acceptor通过accept处理连接请求,然后创建一个Handler对象处理连接完成后的后续业务处理

  4. 如果不是建立连接事件,则Reactor会分发调用连接对应的Handler来响应

  5. worker线程池会分配独立线程完成真正的业务,并将结果返回给Handler

  6. handler接收到响应后,通过send将结果返回给client

优缺点:

  • 优点:可以充分利用多核cpu的处理能力

  • 缺点:多线程数据共享和访问比较复杂,reactor处理所有的事件的监听和响应,在单线程运行,在高并发场景容易出现瓶颈

  • 主从Reactor多线程

    在这里插入图片描述

  1. Reactor主线程MainReactor对象通过select监听连接事件,接到事件后。通过Acceptor处理连接事件
  2. 当Acceptor处理连接事件后,MainReactor将连接分配给SubReactor
  3. SubReactor将连接加入到队列进行监听,并创建handler进行各种事件处理
  4. 当有新事件发生时,SunReactor就会调用对应的handler处理
  5. handler通过read读取数据,分发给后面的worker线程处理
  6. worker线程池分配独立的worker线程进行业务处理,并返回结果
  7. handler接收到响应后,通过send将结果返回给client
  8. Reactor主线程可以对应多个Reactor子线程,即MainReactor可以关联多个SubReactor

优缺点:

  • 优点:父线程与子线程的数据交互简单职责明确,父线程只需要接收新连接,子线程完成后续的业务处理;父线程与子线程的数据交互简单,Reactor主线程只需要把新连接传给子线程,子线程无需返回数据

  • 缺点:编程复杂度较高

    Netty是基于主从Reactor多线程模型

Reactor模式具有如下优点:

  1. 响应快,不必为单个同步时间所阻塞,虽然Reactor本身是同步的
  2. 可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销
  3. 扩展性好,可以方便的通过增加Reactor实例个数来充分利用cpu资源
  4. 复用性好,Reactor模型本身与具体时间处理逻辑无关,具有很高的复用性

2.2 Netty模型

Netty主要基于主从Reactor多线程模型做了一定的改进

工作原理示意图-简单版

在这里插入图片描述

  1. BossGroup 线程维护Selector , 只关注Accecpt
  2. 当接收到Accept事件,获取到对应的SocketChannel, 封装成 NIOScoketChannel并注册到Worker 线程(事件循环), 并进行维护
  3. 当Worker线程监听到selector 中通道发生自己感兴趣的事件后,就进行处理(就由handler), 注意handler 已经加入到通道

工作原理示意图-进阶版

在这里插入图片描述

工作原理示意图-详细版

在这里插入图片描述

对上图说明小结:

  1. Netty抽象出两组线程池BossGroup专门负责接收客户端的连接,WorkerGroup专门负责网络的读写

  2. BossGroup和WorkerGroup类型都是NioEventLoopGroup

  3. NioEventLoopGroup 相当于一个事件循环组, 这个组中含有多个事件循环 ,每一个事件循环是 NioEventLoop

  4. NioEventLoop 表示一个不断循环的执行处理任务的线程, 每个NioEventLoop 都有一个selector , 用于监听绑定在其上的socket的网络通讯

  5. NioEventLoopGroup 可以有多个线程, 即可以含有多个NioEventLoop

  6. 每个Boss NioEventLoop 循环执行的步骤有3步

    1.轮询accept 事件

    2.处理accept 事件 , 与client建立连接 , 生成NioScocketChannel , 并将其注册到某个worker NIOEventLoop 上的 selector

    3.处理任务队列的任务 , 即 runAllTasks

  7. 每个 Worker NIOEventLoop 循环执行的步骤

    1.轮询read, write 事件

    2.处理i/o事件, 即read , write 事件,在对应NioScocketChannel 处理

    3.处理任务队列的任务 , 即 runAllTasks

  8. 每个Worker NIOEventLoop 处理业务时,会使用pipeline(管道), pipeline 中包含了 channel , 即通过pipeline 可以获取到对应通道, 管道中维护了很多的处理器

3. Netty核心模块组件

3.1 Bootstrap、ServerBootstrap

Bootstrap 意思是引导,一个 Netty 应用通常由一个 Bootstrap 开始,主要作用是配置整个 Netty 程序,串联各个组件,Netty 中 Bootstrap 类是客户端程序的启动引导类,ServerBootstrap 是服务端启动引导类

3.2 Future、ChannelFuture

Netty 中所有的 IO 操作都是异步的,不能立刻得知消息是否被正确处理。但是可以过一会等它执行完成或者直接注册一个监听,具体的实现就是通过 Future 和 ChannelFutures,他们可以注册一个监听,当操作执行成功或失败时监听会自动触发注册的监听事件

3.3 Channel

  1. Netty 网络通信的组件,能够用于执行网络 I/O 操作。
  2. 通过Channel 可获得当前网络连接的通道的状态
  3. 通过Channel 可获得网络连接的配置参数 (例如接收缓冲区大小)
  4. Channel 提供异步的网络 I/O 操作(如建立连接,读写,绑定端口),异步调用意味着任何 I/O 调用都将立即返回,并且不保证在调用结束时所请求的 I/O 操作已完成
  5. 调用立即返回一个 ChannelFuture 实例,通过注册监听器到 ChannelFuture 上,可以 I/O 操作成功、失败或取消时回调通知调用方
  6. 支持关联 I/O 操作与对应的处理程序
  7. 不同协议、不同的阻塞类型的连接都有不同的 Channel 类型与之对应,常用的 Channel 类型:
  • NioSocketChannel,异步的客户端 TCP Socket 连接。
  • NioServerSocketChannel,异步的服务器端 TCP Socket 连接。
  • NioDatagramChannel,异步的 UDP 连接。
  • NioSctpChannel,异步的客户端 Sctp 连接。
  • NioSctpServerChannel,异步的 Sctp 服务器端连接,这些通道涵盖了 UDP 和 TCP 网络 IO 以及文件 IO。

3.4 Selector

  1. Netty 基于 Selector 对象实现 I/O 多路复用,通过 Selector 一个线程可以监听多个连接的 Channel 事件。
  2. 当向一个 Selector 中注册 Channel 后,Selector 内部的机制就可以自动不断地查询(Select) 这些注册的 Channel 是否有已就绪的 I/O 事件(例如可读,可写,网络连接完成等),这样程序就可以很简单地使用一个线程高效地管理多个 Channel

3.5 ChannelHandler及其子类

  1. ChannelHandler是一个接口,处理I/O事件或拦截I/O操作,并将其转发到其ChannelPipeline(业务处理链)中的下一个处理程序

  2. ChannelHandler本身并没有提供很多方法,因为这个接口有许多的方法需要实现,方便使用期间,可以继承它的子类

在这里插入图片描述

我们经常需要自定义一个Handler类去继承ChannelInboundHandlerAdapter,然后通过重写相应方法实现业务逻辑

3.6 Pipeline和ChannelPipeline

  1. ChannelPipeline 是一个 Handler 的集合,它负责处理和拦截 inbound 或者 outbound 的事件和操作,相当于一个贯穿 Netty 的链。(也可以这样理解:ChannelPipeline是 保存ChannelHandler的List,用于处理或拦截 Channel的入站事件和出站操作)
  2. Chan
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值