netty实战之一 认识netty

一.netty是啥?

百度百科简介:

Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。

也就是说,Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务开发。

“快速”和“简单”并不用产生维护性或性能上的问题。Netty 是一个吸收了多种协议(包括FTP、SMTP、HTTP等各种二进制文本协议)的实现经验,并经过相当精心设计的项目。最终,Netty 成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性。

简单来说就是netty是JBoss做的一个Jar包,为了快速开发高性能、高可靠性的网络服务器和客户端程序,可以提供异步的、事件驱动的网络应用程序框架和工具

netty组成(后续文章会详细介绍)

 我们可以先从总体上认识一下Netty用到的组件及它们在整个Netty架构中是怎么协调工作的。Netty应用中必不可少的组件:

  1. Bootstrap or ServerBootstrap
  2. EventLoop
  3. EventLoopGroup
  4. ChannelPipeline
  5. Channel
  6. Future or ChannelFuture
  7. ChannelInitializer
  8. ChannelHandler

     Bootstrap,一个Netty应用通常由一个Bootstrap开始,它主要作用是配置整个Netty程序,串联起各个组件。

     Handler,为了支持各种协议和处理数据的方式,便诞生了Handler组件。Handler主要用来处理各种事件,这里的事件很广泛,比如可以是连接、数据接收、异常、数据转换等。

     ChannelInboundHandler,一个最常用的Handler。这个Handler的作用就是处理接收到数据时的事件,也就是说,我们的业务逻辑一般就是写在这个Handler里面的,ChannelInboundHandler就是用来处理我们的核心业务逻辑。

     ChannelInitializer,当一个链接建立时,我们需要知道怎么来接收或者发送数据,当然,我们有各种各样的Handler实现来处理它,那么ChannelInitializer便是用来配置这些Handler,它会提供一个ChannelPipeline,并把Handler加入到ChannelPipeline。

     ChannelPipeline,一个Netty应用基于ChannelPipeline机制,这种机制需要依赖于EventLoop和EventLoopGroup,因为它们三个都和事件或者事件处理相关。

     EventLoops的目的是为Channel处理IO操作,一个EventLoop可以为多个Channel服务。

     EventLoopGroup会包含多个EventLoop。

     Channel代表了一个Socket链接,或者其它和IO操作相关的组件,它和EventLoop一起用来参与IO处理。

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

2.1netty重要组件的关系图解

  • 2.1.1.ServerBootstrap及Bootstrap的类继承结构图

  • 2.1.2.下图是Channel、EventLoop、Thread、EventLoopGroup之间的关系(摘自《Netty In Action》):

  • 2.1.2 下图显示了ServerBootstrap的两个EventLoopGroup

二.netty能干嘛?

Netty 在哪些行业得到了应用?互联网行业:随着网站规模的不断扩大,系统并发访问量也越来越高,传统基于 Tomcat 等 Web 容器的垂直架构已经无法满足需求,需要拆分应用进行服务化,以提高开发和维护效率。从组网情况看,垂直的架构拆分之后,系统采用分布式部署,各个节点之间需要远程服务调用,高性能的 RPC 框架必不可少,Netty 作为异步高性能的通信框架,往往作为基础通信组件被这些 RPC 框架使用。典型的应用有:阿里分布式服务框架 Dubbo 的 RPC 框架使用 Dubbo 协议进行节点间通信,Dubbo 协议默认使用 Netty 作为基础通信组件,用于实现各进程节点之间的内部通信

其中,服务提供者和服务消费者之间,服务提供者、服务消费者和性能统计节点之间使用 Netty 进行异步/同步通信。除了 Dubbo 之外,淘宝的消息中间件 RocketMQ 的消息生产者和消息消费者之间,也采用 Netty 进行高性能、异步通信。除了阿里系和淘宝系之外,很多其它的大型互联网公司或者电商内部也已经大量使用 Netty 构建高性能、分布式的网络服务器。游戏行业:无论是手游服务端、还是大型的网络游戏,Java 语言得到了越来越广泛的应用。Netty 作为高性能的基础通信组件,它本身提供了 TCP/UDP 和 HTTP 协议栈,非常方便定制和开发私有协议栈。账号登陆服务器、地图服务器之间可以方便的通过 Netty 进行高性能的通信。

Netty 在游戏服务器架构中的应用大数据领域:经典的 Hadoop 的高性能通信和序列化组件 Avro 的 RPC 框架,默认采用 Netty 进行跨节点通信,它的 Netty Service 基于 Netty 框架二次封装实现。大数据计算往往采用多个计算节点和一个/N个汇总节点进行分布式部署,各节点之间存在海量的数据交换。由于 Netty 的综合性能是目前各个成熟 NIO 框架中最高的,因此,往往会被选中用作大数据各节点间的通信。企业软件:企业和 IT 集成需要 ESB,Netty 对多协议支持、私有协议定制的简洁性和高性能是 ESB RPC 框架的首选通信组件。事实上,很多企业总线厂商会选择 Netty 作为基础通信组件,用于企业的 IT 集成。通信行业:Netty 的异步高性能、高可靠性和高成熟度的优点,使它在通信行业得到了大量的应用

三.netty其他特点

设计

  • 统一的 API,适用于不同的协议(阻塞和非阻塞)

  • 基于灵活、可扩展的事件驱动模型

  • 高度可定制的线程模型

  • 可靠的无连接数据 Socket 支持(UDP)

性能

  • 更好的吞吐量,低延迟

  • 更省资源

  • 尽量减少不必要的内存拷贝

安全

  • 完整的 SSL/TLS 和 STARTTLS 的支持

易用

  • 完善的 Java doc,用户指南和样例,社区很活跃

  • 简洁简单

  • 仅依赖于 JDK1.5

Netty框架

核心部分

  • 零拷贝

    “Zero-copy” describes computer operations in which the CPU does not perform the task of copying data from one memory area to another.

    上面是 wiki 的一描述,它通常是指计算机在网络上发送文件时,不需要将文件内容拷贝到用户空间(User Space)而直接在内核空间(Kernel Space)中传输到网络的方式,所谓的两个空间只是说明两个不一样的内存区域,通过减少不同内存区域的拷贝,减低 CPU 的消耗。下面有两张对比图:

    1、非零拷贝模式

       2、零拷贝模式

Netty 的零拷贝与实际定义还是有点出入,Java 是基于虚拟机的,其实都是用户空间,Netty 中的零拷贝,更多的是一种数据的优化操作,比如多包合并处理上,Netty是将各个包的地址记录下来,在逻辑上合成一个整体,实际存储还是独立的,这样减少内存拷贝,降低 CPU 消耗。

  • 统一通讯 API

    Netty 提供了命名为 channel 统一异步 IO 接口,主要是为了解决 Java OIO , NIO API 不兼容,简化业务层的工作。

  • 可扩展的事件模型

    Netty has a well-defined event model focused on I/O. It also allows you to implement your own event type without breaking the existing code because each event type is distinguished from another by a strict type hierarchy. This is another differentiator against other frameworks.

Netty 是通过 ChannelEvent 作为事件流载体,通过 ChannelHander 来做事件逻辑处理,channelHander 又可分为 INBoundHandler 和 OUTBoundHandler 分别处理流入数据和流出数据,Event 则通过 sendDownStream 和 sendUpStream 在每个 handler 中流转,ChannelPipeline 作为 handler 的容器,用户自定义的 handler 只要添加到   pipe,就可以截取数据流做业务处理。

所有的数据流转,和执行过程都是在一个线程(EventLoop)上执行的,这种串行化的处理方式,让 Netty 无锁化,无需处理数据竞争问题,提高了执行效率。

高级组件

  • 编解码框架

    Netty 提供里提供一套 EncodeHandler 和 DecodeHandler,将业务逻辑从编解码分离,大家可以了解一下,有时间会对这块仔细说明

  • SSL/TLS Support

    在 Netty 中使用 SSL 也是很方便的,使用 SSLEngine,SslHandler 就可以

  • Http/WebSocket 支持

Netty线程模型

Netty 支持三种线程模型,分别是单线程模型,多线程模型,以及主从线程模型,重点会介绍主从多线程模型

  • 单线程模型

从 accpet 连接到分发到 handler 处理业务,都在单线程中完成,模型简单,适合简单场景,不适合大并发场景。

  • 多线程模型

  1. Acceptor 单独线程接受 accpet 连接请求,创建 Channel,并移交给 IO 线程池

  2. IO 线程池分配线程读取 Channel 数据,并分发 handler 处理相关业务

  3. Accpetor 是单线程,如果期间执行鉴权,登陆等操作,出现拥堵,会有单点问题。

  • 主从多线程模型

  1. Acceptor 线程池(NioEventLoopGroup)分配一个 NioEventLoop 接受连接请求,并创建 Channel,并将 Channel 移交给 IO 线程池

  2. I/O 线程池((NioEventLoopGroup)分配一个 NioEventLoop 处理 Channel 数据,从 Channel 读数据,并将数据交给 handler 处理,handler 处理完后,向 Channel 写数据

  3. I/O 线程池还可以处理定时任务,和系统任务。

这边多次提到 NioEventLoop,许多个 NioEventLoop 构成 NioEventLoopGroup,其主要的职能如下:

  1. 作为 Acceptor 线程,负责处理客户端的请求接入

  2. 作为 Connecor 线程,负责注册监听连接操作位,用于判断异步连接结果

  3. 作为 IO 线程,监听网络读操作位,负责从 SocketChannel 中读取写报文

这张图很好的说明 NioEventLoop 的作用,以及 Netty 串行化的处理链。

  • 一个客户端 Channel 只能由一个 NioEventLoop 处理,避免并发资源竞争问题。

  • NioEventLoop 的事件是分发给 Netty 的事件模型,这个模型可以参考上面的说明。

总结

本文主要介绍了 Netty 的原理,重点对 Netty 的串行化处理链,线程模型,数据模型做了说明,绕过了细节,希望对大家在大层面去理解 Netty 有帮助,更多的实践,以及细节,留在后续文章再说。

猜你喜欢

转载自blog.csdn.net/weixin_39666581/article/details/81150189
今日推荐