Netty整体介绍和架构认知(一)

简介: Netty整体介绍和架构认知

一、初识Netty

1.1 本质:网络应用程序框架

Netty 是一款用于高效开发网络应用的 NIO 网络框架,它大大简化了网络应用的开发过程。我们所熟知的 TCP 和 UDP 的 Socket 服务器开发,就是一个有关 Netty 简化网络应用开发的典型案例。

既然 Netty 是网络应用框架,那我们永远绕不开以下几个核心关注点:

  • I/O 模型、线程模型和事件处理机制;
  • 易用性 API 接口;
  • 对数据协议、序列化的支持。

我们之所以会最终选择 Netty,是因为 Netty 围绕这些核心要点可以做到尽善尽美,其健壮性、性能、可扩展性在同领域的框架中都首屈一指。下面我们从以下三个方面一起来看看,Netty 到底有多厉害。

高性能,低延迟

经常听到这么一句话:“网络编程只要你使用了 Netty 框架,你的程序性能基本就不会差。”这句话虽然有些绝对,但是也从侧面上反映了人们对 Netty 高性能的肯定。

实现高性能的网络应用框架离不开 I/O 模型问题,在了解 Netty 高性能原理之前我们需要先储备 I/O 模型的基本知识。

I/O 请求可以分为两个阶段,分别为调用阶段和执行阶段。

  • 第一个阶段为I/O 调用阶段,即用户进程向内核发起系统调用。
  • 第二个阶段为I/O 执行阶段。此时,内核等待 I/O 请求处理完成返回。该阶段分为两个过程:首先等待数据就绪,并写入内核缓冲区;随后将内核缓冲区数据拷贝至用户态缓冲区。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uR9YRc5K-1610009345267)(https://s0.lgstatic.com/i/image/M00/60/29/Ciqc1F-NAZ6Ae3bPAAHigveMsIQ514.png)]

了解了上述五种 I/O,再来看 Netty 如何实现自己的 I/O 模型。Netty 的 I/O 模型是基于非阻塞 I/O 实现的,底层依赖的是 JDK NIO 框架的多路复用器 Selector。一个多路复用器 Selector 可以同时轮询多个 Channel,采用 epoll 模式后,只需要一个线程负责 Selector 的轮询,就可以接入成千上万的客户端。

在 I/O 多路复用的场景下,当有数据处于就绪状态后,需要一个事件分发器(Event Dispather),它负责将读写事件分发给对应的读写事件处理器(Event Handler)。事件分发器有两种设计模式:Reactor 和 Proactor,Reactor 采用同步 I/O, Proactor 采用异步 I/O。

Reactor 实现相对简单,适合处理耗时短的场景,对于耗时长的 I/O 操作容易造成阻塞。

Proactor 性能更高,但是实现逻辑非常复杂,目前主流的事件驱动模型还是依赖 select 或 epoll 来实现。

上图所描述的便是 Netty 所采用的主从 Reactor 多线程模型,所有的 I/O 事件都注册到一个 I/O 多路复用器上,当有 I/O 事件准备就绪后,I/O 多路复用器会将该 I/O 事件通过事件分发器分发到对应的事件处理器中。该线程模型避免了同步问题以及多线程切换带来的资源开销,真正做到高性能、低延迟。

在 JDK 1.4 投入使用之前,只有 BIO 一种模式。开发过程相对简单。新来一个连接就会创建一个新的线程处理。随着请求并发度的提升,BIO 很快遇到了性能瓶颈。

JDK 1.4 以后开始引入了 NIO 技术,支持 select 和 poll;JDK 1.5 支持了 epoll;JDK 1.7 发布了 NIO2,支持 AIO 模型。Java 在网络领域取得了长足的进步。

既然 JDK NIO 性能已经非常优秀,为什么还要选择 Netty?这是因为 Netty 做了 JDK 该做的事,但是做得更加完备。我们一起看下 Netty 相比 JDK NIO 有哪些突出的优势。

Netty相比JDK的NIO的优势

优势一:

优势二:

优势三:

解决方案:

  • 易用性。 我们使用 JDK NIO 编程需要了解很多复杂的概念,比如 Channels、Selectors、Sockets、Buffers 等,编码复杂程度令人发指。相反,Netty 在 NIO 基础上进行了更高层次的封装,屏蔽了 NIO 的复杂性;Netty 封装了更加人性化的 API,统一的 API(阻塞/非阻塞) 大大降低了开发者的上手难度;与此同时,Netty 提供了很多开箱即用的工具,例如常用的行解码器、长度域解码器等,而这些在 JDK NIO 中都需要你自己实现。
  • 稳定性。 Netty 更加可靠稳定,修复和完善了 JDK NIO 较多已知问题,例如臭名昭著的 select 空转导致 CPU 消耗 100%,TCP 断线重连,keep-alive 检测等问题。
  • 可扩展性。 Netty 的可扩展性在很多地方都有体现,这里主要列举其中的两点:一个是可定制化的线程模型,用户可以通过启动的配置参数选择 Reactor 线程模型;另一个是可扩展的事件驱动模型,将框架层和业务层的关注点分离。大部分情况下,开发者只需要关注 ChannelHandler 的业务逻辑实现。
  • 更低的资源消耗作为网络通信框架,需要处理海量的网络数据,那么必然面临有大量的网络对象需要创建和销毁的问题,对于 JVM GC 并不友好。为了降低 JVM 垃圾回收的压力,Netty 主要采用了两种优化手段:
  • 对象池复用技术。 Netty 通过复用对象,避免频繁创建和销毁带来的开销。
  • 零拷贝技术。 除了操作系统级别的零拷贝技术外,Netty 提供了更多面向用户态的零拷贝技术,例如 Netty 在 I/O 读写时直接使用 DirectBuffer,从而避免了数据在堆内存和堆外内存之间的拷贝。

因为 Netty 不仅做到了高性能、低延迟以及更低的资源消耗,还完美弥补了 Java NIO 的缺陷,所以在网络编程时越来越受到开发者们的青睐。

网络框架的选型

很多开发者都使用过 Tomcat,Tomcat 作为一款非常优秀的 Web 服务器看上去已经帮我们解决了类似问题,那么它与 Netty 到底有什么不同?

Netty 和 Tomcat 最大的区别在于对通信协议的支持,可以说 Tomcat 是一个 HTTP Server,它主要解决 HTTP 协议层的传输,而 Netty 不仅支持 HTTP 协议,还支持 SSH、TLS/SSL 等多种应用层的协议,而且能够自定义应用层协议。

Tomcat 需要遵循 Servlet 规范,在 Servlet 3.0 之前采用的是同步阻塞模型,Tomcat 6.x 版本之后已经支持 NIO,性能得到较大提升。然而 Netty 与 Tomcat 侧重点不同,所以不需要受到 Servlet 规范的约束,可以最大化发挥 NIO 特性。

如果你仅仅需要一个 HTTP 服务器,那么我推荐你使用 Tomcat。术业有专攻,Tomcat 在这方面的成熟度和稳定性更好。但如果你需要做面向 TCP 的网络应用开发,那么 Netty 才是你最佳的选择。

此外,比较出名的网络框架还有 Mina 和 Grizzly。Mina 是 Apache Directory 服务器底层的 NIO 框架,由于 Mina 和 Netty 都是 Trustin Lee 主导的作品。Grizzly 出身 Sun 公司,从设计理念上看没有 Netty 优雅,几乎是对 Java NIO 比较初级的封装,目前业界使用的范围也很小。

如果没有项目历史包袱,目前主流推荐 Netty 4.x 的稳定版本,Netty 3.x 到 4.x 版本发生了较大变化,属于不兼容升级,下面我们初步了解下 4.x 版本有哪些值得关注的变化和新特性。

项目结构:模块化程度更高,包名从 org.jboss.netty 更新为 io.netty,不再属于 Jboss。

  • ChannelBuffer 变更为 ByteBuf,Buffer 相关的工具类可以独立使用。由于人性化的 Buffer API 设计,它已经成为 Java ByteBuffer 的完美替代品。
  • Buffer 统一为动态变化,可以更安全地更改 Buffer 的容量。
  • 增加新的数据类型 CompositeByteBuf,可以用于减少数据拷贝。
  • GC 更加友好,增加池化缓存,4.1 版本开始 jemalloc 成为默认内存分配方式。
  • 内存泄漏检测功能。
  • 通用工具类:io.netty.util.concurrent 包中提供了较多异步编程的数据结构。
  • 更加严谨的线程模型控制,降低用户编写 ChannelHandler 的心智,不必过于担心线程安全问题。

可见 Netty 4.x 带来了很多提升,性能、健壮性都变得更加强大了。Netty 精益求精的设计精神值得每个人学习。当然,其中还有更多细节变化,感兴趣的可以参考以下网址:https://netty.io/wiki/new-and-noteworthy-in-4.0.html

综上所述,Netty 是我们一个较好的选择。

  • 实现:异步、事件驱动
  • 特性:高性能、可维护、快速开发
  • 用途: 开发服务器和客户端


相关文章
|
7月前
|
Web App开发 前端开发 Java
Apache Zeppelin系列教程第二篇——整体架构
Apache Zeppelin系列教程第二篇——整体架构
171 0
|
7月前
|
存储 安全 Java
SpringCloud整体架构概述
SpringCloud整体架构概述
155 0
|
5月前
|
监控 Kubernetes 安全
Istio整体架构解析
【7月更文挑战第17天】Istio整体架构分为数据平面(Data Plane)和控制平面(Control Plane)两部分
|
消息中间件 前端开发 安全
【开篇 | Spring深度学习】Spring设计理念和整体架构
【开篇 | Spring深度学习】Spring设计理念和整体架构
76 0
|
7月前
|
存储 SQL 分布式计算
TiDB整体架构概览:构建高效分布式数据库的关键设计
【2月更文挑战第26天】本文旨在全面概述TiDB的整体架构,深入剖析其关键组件和功能,从而帮助读者理解TiDB如何构建高效、稳定的分布式数据库。我们将探讨TiDB的计算层、存储层以及其他核心组件,并解释这些组件是如何协同工作以实现卓越的性能和扩展性的。通过本文,读者将能够深入了解TiDB的整体架构,为后续的学习和实践奠定坚实基础。
|
7月前
|
SQL 前端开发 JavaScript
前端后端技术栈分类和整体架构
前端后端技术栈分类和整体架构
|
7月前
|
机器学习/深度学习 资源调度 并行计算
VGen整体架构
【1月更文挑战第7天】VGen整体架构
221 1
VGen整体架构
|
7月前
|
前端开发 网络协议 Dubbo
Netty - 回顾Netty高性能原理和框架架构解析
Netty - 回顾Netty高性能原理和框架架构解析
291 0
|
消息中间件 NoSQL Kafka
微服务轮子项目(01) - 整体架构
微服务轮子项目(01) - 整体架构
102 0
|
数据采集 SQL 数据可视化
79 网站点击流数据分析案例(整体技术流程及架构)
79 网站点击流数据分析案例(整体技术流程及架构)
122 0