一文看懂 Netty 架构设计
本文重点分析 Netty 的逻辑架构及关键的架构质量属性,希望有助于大家从 Netty 的架构设计中汲取营养,设计出高性能、高可靠性和可扩展的程序。
Netty 的三层架构设计
Netty 采用了典型的三层网络架构进行设计和开发,其逻辑架构图如下所示。
通信调度层 Reactor
它由一系列辅助类完成,包括 Reactor 线程 NioEventLoop 及其父类,NioSocketChannel / NioServerSocketChannel 及其父类,Buffer 组件,Unsafe 组件 等。该层的主要职责就是监听网络的读写和连接操作,负责将网络层的数据读取到内存缓冲区,然后触发各种网络事件,例如连接创建、连接激活、读事件、写事件等,将这些事件触发到 PipeLine 中,由 PipeLine 管理的责任链来进行后续的处理。
责任链层 Pipeline
它负责上述的各种网络事件在责任链中的有序传播,同时负责动态地编排责任链。责任链可以选择监听和处理自己关心的事件,它可以拦截处理事件,以及向前向后传播事件。不同应用的 Handler 节点 的功能也不同,通常情况下,往往会开发编解码 Hanlder 用于消息的编解码,可以将外部的协议消息转换成 内部的 POJO 对象,这样上层业务则只需要关心处理业务逻辑即可,不需要感知底层的协议差异和线程模型差异,实现了架构层面的分层隔离。
业务逻辑编排层 Service ChannelHandler
业务逻辑编排层通常有两类:一类是纯粹的业务逻辑编排,还有一类是其他的应用层协议插件,用于特定协议相关的会话和链路管理。例如,CMPP 协议,用于管理和中国移动短信系统的对接。
架构的不同层面,需要关心和处理的对象都不同,通常情况下,对于业务开发者,只需要关心责任链的拦截和业务 Handler 的编排。因为应用层协议栈往往是开发一次,到处运行,所以实际上对于业务开发者来说,只需要关心服务层的业务逻辑开发即可。各种应用协议以插件的形式提供,只有协议开发人员需要关注协议插件,对于其他业务开发人员来说,只需关心业务逻辑定制。这种分层的架构设计理念实现了 NIO 框架 各层之间的解耦,便于上层业务协议栈的开发和业务逻辑的定制。
正是由于 Netty 的分层架构设计非常合理,基于 Netty 的各种应用服务器和协议栈开发才能够如雨后春笋般得到快速发展。
关键的架构质量属性
性能
影响最终产品的性能因素非常多,其中软件因素如下:
•架构不合理导致的性能问题;•编码实现不合理导致的性能问题,例如,锁没用好导致的性能瓶颈。
硬件因素如下:
•服务器硬件配置太低导致的性能问题;•带宽、磁盘的 IOPS 等限制导致的 IO 操作 性能差;•测试环境被共用导致被测试的软件产品受到影响。
尽管影响产品性能的因素非常多,但是架构的性能模型合理与否对性能的影响非常大。如果一个产品的架构设计得不好,无论开发如何努力,都很难开发出一个高性能、高可用的软件产品。
“性能是设计出来的,而不是测试出来的”。
下面我们看看 Netty 的架构设计是如何实现高性能的。
1.采用非阻塞的 NIO 类库,基于 Reactor 模式实现,解决了传统同步阻塞 IO 模式下一个服务端无法平滑地处理线性增长的客户端的问题。2.TCP 接收和发送缓冲区使用直接内存代替堆内存,避免了内存复制,提升了 IO 读取和写入的性能。3.支持通过内存池的方式循环利用 ByteBuffer,避免了频繁创建和销毁 ByteBuffer 带来的性能损耗。4.可配置的 IO 线程数、TCP 参数等,为不同的用户场景提供定制化的调优参数,满足不同的性能场景。5.采用环形数组缓冲区实现无锁化并发编程,代替传统的线程安全容器或者锁。6.合理地使用线程安全容器、原子类等,提升系统的并发处理能力。7.关键资源的处理使用单线程串行化的方式,避免多线程并发访问带来的锁竞争和额外的 CPU 资源消耗问题。8.通过引用计数器及时地申请释放不再被引用的对象,细粒度的内存管理降低了 GC 的频率,减少了频繁 GC 带来的延时和 CPU 损耗。
可靠性
作为一个高性能的异步通信框架,架构的可靠性是大家选择的另一个重要依据。下面我们看一下 Netty 架构 的可靠性设计。
1. 链路有效性检测
由于长连接不需要每次发送消息都创建链路,也不需要在消息交互完成时关闭链路,因此相对于短连接性能更高。对于长连接,一旦链路建立成功便一直维系双方之间的链路,直到系统退出。
为了保证长连接的链路有效性,往往需要通过心跳机制周期性地进行链路检测。使用周期性心跳的原因是:在系统空闲时,例如凌晨,往往没有业务消息。如果此时链路被防火墙 Hang 住,或者遭遇网络闪断、网络单通等,通信双方无法识别出这类链路异常。等到第二天业务高峰期到来时,瞬间的海量业务冲击会导致消息积压无法发送给对方,由于链路的重建需要时间,这期间业务会大量失败 (集群或者分布式组网情况会好一些)。为了解决这个问题,需要周期性的 “心跳检测” 对链路进行有效性检查,一旦发生问题,可以及时关闭链路,重建 TCP 连接。
当有业务消息时,无须心跳检测,可以由业务消息进行链路可用性检测。所以心跳消息往往是在链路空闲时发送的。为了支持心跳机制,Netty 提供了如下两种链路空闲检测机制。
•读空闲超时机制:当经过 连续的周期 T 没有消息可读时,触发 超时 Handler,用户可以基于 该读空闲超时 Handler 发送心跳消息,进行链路检测,如果连续 N 个周期 仍然没有读取到心跳消息,可以主动关闭这条链路。•写空闲超时机制:当经过 连续的周期 T 没有消息要发送时,触发 超时 Handler,用户可以基于 该写空闲超时 Handler 发送心跳消息,进行链路检测,如果连续 N 个周期 仍然没有接收到对方的心跳消息,可以主动关闭这条链路。
为了满足不同用户场景的心跳定制,Netty 提供了空闲状态检测事件通知机制,用户可以订阅:空闲超时事件、读空闲超时机制、写空闲超时事件,在接收到对应的空闲事件之后,灵活地进行定制。
2. 内存保护机制
Netty 提供多种机制对内存进行保护,包括以下几个方面:
•通过对象引用计数器对 Netty 的 ByteBuffer 等内置对象进行细粒度的内存申请和释放,对非法的对象引用进行检测和保护。•通过内存池来重用 ByteBuffer,节省内存。•可设置的内存容量上限,包括 ByteBuffer、线程池线程数等。
可定制性
Netty 的可定制性主要体现在以下几点:
•责任链模式:ChannelPipeline 基于责任链模式开发,便于业务逻辑的拦截、定制和扩展。•基于接口的开发:关键的类库都提供了接口或者抽象类,如果 Netty 自身的实现无法满足用户的需求,可以由用户自定义实现相关接口。•提供了大量工厂类,通过重载这些工厂类可以按需创建出用户实现的对象。•提供了大量的系统参数供用户按需设置,增强系统的场景定制性。
可扩展性
基于 Netty 的 基本 NIO 框架,可以方便地进行应用层协议定制,例如,HTTP 协议栈、Thrift 协议栈、FTP 协议栈 等。这些扩展不需要修改 Netty 的源码,直接基于 Netty 的二进制类库即可实现协议的扩展和定制。目前,业界存在大量的基于 Netty 框架开发的协议,例如基于 Netty 的 HTTP 协议、Dubbo 协议、RocketMQ 内部私有协议 等。
一文看懂 Netty 架构设计的更多相关文章
- 从字符串到常量池,一文看懂String类设计
从一道面试题开始 看到这个标题,你肯定以为我又要讲这道面试题了 // 这行代码创建了几个对象? String s3 = new String("1"); 是的,没错,我确实要从这里 ...
- 【转帖】一文看懂docker容器技术架构及其中的各个模块
一文看懂docker容器技术架构及其中的各个模块 原创 波波说运维 2019-09-29 00:01:00 https://www.toutiao.com/a6740234030798602763/ ...
- 一文看懂java io系统 (转)
出处: 一文看懂java io系统 学习java IO系统,重点是学会IO模型,了解了各种IO模型之后就可以更好的理解java IO Java IO 是一套Java用来读写数据(输入和输出)的A ...
- 一文看懂大数据的技术生态圈,Hadoop,hive,spark都有了
一文看懂大数据的技术生态圈,Hadoop,hive,spark都有了 转载: 大数据本身是个很宽泛的概念,Hadoop生态圈(或者泛生态圈)基本上都是为了处理超过单机尺度的数据处理而诞生的.你可以把它 ...
- 转载来自朱小厮博客的 一文看懂Kafka消息格式的演变
转载来自朱小厮博客的 一文看懂Kafka消息格式的演变 ✎摘要 对于一个成熟的消息中间件而言,消息格式不仅关系到功能维度的扩展,还牵涉到性能维度的优化.随着Kafka的迅猛发展,其消息格式也在 ...
- 一文看懂YOLO v3
论文地址:https://pjreddie.com/media/files/papers/YOLOv3.pdf论文:YOLOv3: An Incremental Improvement YOLO系列的 ...
- 一文看懂web服务器、应用服务器、web容器、反向代理服务器区别与联系
我们知道,不同肤色的人外貌差别很大,而双胞胎的辨识很难.有意思的是Web服务器/Web容器/Web应用程序服务器/反向代理有点像四胞胎,在网络上经常一起出现.本文将带读者对这四个相似概念如何区分. 1 ...
- 一文看懂https如何保证数据传输的安全性的【转载、收藏】
一文看懂https如何保证数据传输的安全性的 一文看懂https如何保证数据传输的安全性的 大家都知道,在客户端与服务器数据传输的过程中,http协议的传输是不安全的,也就是一般情况下http是明 ...
- [转帖]一文看懂web服务器、应用服务器、web容器、反向代理服务器区别与联系
一文看懂web服务器.应用服务器.web容器.反向代理服务器区别与联系 https://www.cnblogs.com/vipyoumay/p/7455431.html 我们知道,不同肤色的人外貌差别 ...
随机推荐
- 资深CIO介绍如何选型OA系统的?
OA办公系统成为企业管理的标配软件,在于可有效加强组织管理能力,提高员工协同效率,助力企业科学决策,合理分配企业资源,提升企业综合实力与市场竞争力.企业OA选型的经验总结来说也就是品牌.技术.产品.服 ...
- 一起学Blazor WebAssembly 开发(3)
接着上篇,本篇开始讲下实现登录窗口,先看下大概的效果图: 打开的效果,没有美工美化 点登录校验得到不能为空 我在做blazor时用到了一个ui框架,这个框架名叫Ant Design blazor(ht ...
- presto和hive日期函数对比
时间格式转换 日期格式→Unix时间戳 转10位Unix时间戳 数据:2020-07-23 15:01:13 Presto:select to_unixtime(cast('2020-07-23 15 ...
- 跟老刘学运维day01~谈红帽系统
第0章 谈红帽系统 1.Linux,是一套免费使用和自由传播的类Unix操作系统,其源代码完全开源: 开源:==>将程序与程序的源代码一起提供给用户的服务模式. 开源四大特点:低风险.高品质.低 ...
- java基础(九)--方法重载
如System.out.println()方法即是方法重载的. 以下举例说明自定义sum()方法的重载 package cnblogs; public class TestBase09MathRelo ...
- 论文阅读 ORBSLAM3
这周末ORB-SLAM3出现了.先看了看论文.IMU部分没细看,后面补上. Abstract 视觉,视觉惯导,多地图SLAM系统 支持单目/立体/RGBD相机 支持pinhole/鱼眼相机 基于特征/ ...
- python基础全部知识点整理,超级全(20万字+)
目录 Python编程语言简介 https://www.cnblogs.com/hany-postq473111315/p/12256134.html Python环境搭建及中文编码 https:// ...
- Python 数字类型转换
Python数字类型转换: int(x):将 x 转换为一个整数 float(x):将 x 转换为一个浮点数 complex(x,y):将 x 和 y 转换为一个复数.x 为复数的实部,y 为复数的虚 ...
- C/C++编程笔记:C语言写推箱子小游戏,大一学习C语言练手项目
C语言,作为大多数人的第一门编程语言,重要性不言而喻,很多编程习惯,逻辑方式在此时就已经形成了.这个是我在大一学习 C语言 后写的推箱子小游戏,自己的逻辑能力得到了提升,在这里同大家分享这个推箱子小游 ...
- linux之shell基本认知操作和简单shell练习
shell编程: 1.Shell的作用 命令解释器,“翻译官”.介于操作系统内核与用户之间,负责解释命令行. shell功能非常强大,除负责解释名另外,还可以将多个命令组合起来,完成复杂的任务,这就是 ...