Netty 基本原理
之前在看rocketmq源码时,发现底层用了Netty,顺便学习了一下,网上不少博客讲的有错误之处,而且大部分一模一样,估计大部分都是复制别人的。为了不被误导,我专门买了本《Netty权威指南》,仔细阅读了一遍,而且微信请教了锋哥(李林锋),遂整理出这篇分享。
本人一直秉承原则:宁愿不写、少写,也尽量不写错的知识!以免误人子弟!
希望转载的同学,标出原文链接。谢谢!同时非常欢迎指出错误,本人及时修正!
版本说明
Netty3(3.x)版本是比较旧的版本。
Netty4(4.x)版本是当前官方推荐的,目前一直在维护中。跟3.x版本相比变化比较大,特别是API。
Netty5(5.x)是被舍弃的版本,官方不推荐使用!
Netty5舍弃的官方解释:
1. netty5中使用了 ForkJoinPool,增加了代码的复杂度,但是对性能的改善却不明显
2. 多个分支的代码同步工作量很大
3. 作者觉得当下还不到发布一个新版本的时候
4. 在发布版本之前,还有更多问题需要调查一下,比如是否应该废弃 exceptionCaught,是否暴露EventExecutorChooser等等。
参考:https://github.com/netty/netty/issues/4466
1. Netty基本概念
Netty是一个高性能、异步事件驱动的NIO框架,它提供了对TCP、UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果。
作为当前最流行的NIO框架,Netty在互联网领域、大数据分布式计算领域、游戏行业、通信行业等获得了广泛的应用,一些业界著名的开源组件也基于Netty的NIO框架构建。如:Dubbo、 RocketMQ、Hadoop的Avro、Spark等。
Netty需要学习的内容: 编解码器、TCP粘包/拆包及Netty如何解决、ByteBuf、Channel和Unsafe、ChannelPipeline和ChannelHandler、EventLoop和EventLoopGroup、Future等。
编解码器:
Java序列化的目的主要有两个:
- 网络传输
- 对象持久化
Java序列化仅仅是Java编解码技术的一种,由于他的种种缺陷,衍生出多种编解码技术和框架。
Java序列化的缺点:
- 无法跨语言
- 序列化后的码流太大
- 序列化性能太低
业界主流的编解码框架:
- Google Protobuf:支持Java、C++、Python三种语言,高效的编码性能,结构化数据存储格式(XML,JSON等)
- Facebook Thrift:适用于静态的数据交换,需要先确定好它的数据结构。结构变化后需要重新编译IDL文件,这也是Thrift的弱项。
- JBoss Marshalling:是一个Java对象的序列化API,修正了JDK自带的序列化包的很多问题,但又保持跟java.io.Serializable接口的兼容。
- Hessian:一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能,采用的是二进制RPC协议。
TCP粘包/拆包:
TCP是个“流”协议,所谓流,就是没有界限的一串数据。TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓存区的实际情况进行包的划分,所以在业务上的一个完整的包,可能被TCP拆分成多个包进行发送,也可能把多个小包封装成一个大的数据包发送,这就是TCP粘包和拆包问题。
有如下几种情况:
正常情况

粘包

粘包和拆包同时发生

2. Netty线程模型
在JAVA NIO方面Selector给Reactor模式提供了基础,Netty结合Selector和Reactor模式设计了高效的线程模型。
关于Java NIO 构造Reator模式,Doug Lea在《Scalable IO in Java》中给了很好的阐述,这里截取PPT对Reator模式的实现进行说明。
(1)Reactor单线程模型

这是最简单的Reactor单线程模型,由于Reactor模式使用的是异步非阻塞IO,所有的IO操作都不会被阻塞,理论上一个线程可以独立处理所有的IO操作。这时Reactor线程是个多面手,负责多路分离套接字,Accept新连接,并分发请求到处理链中。
对于一些小容量应用场景,可以使用到单线程模型。但对于高负载,大并发的应用却不合适,主要原因如下:
1. 当一个NIO线程同时处理成百上千的链路,性能上无法支撑,即使NIO线程的CPU负荷达到100%,也无法完全处理消息。
2. 当NIO线程负载过重后,处理速度会变慢,会导致大量客户端连接超时,超时之后往往会重发,更加重了NIO线程的负载。
3. 可靠性低,一个线程意外死循环,会导致整个通信系统不可用。
为了解决这些问题,出现了Reactor多线程模型。
(2)Reactor多线程模型

相比上一种模式,该模型在处理链部分采用了多线程(线程池)。
在绝大多数场景下,该模型都能满足性能需求。但是,在一些特殊的应用场景下,如服务器会对客户端的握手消息进行安全认证。这类场景下,单独的一个Acceptor线程可能会存在性能不足的问题。为了解决这些问题,产生了第三种Reactor线程模型。
(3)Reactor主从模型

该模型相比第二种模型,是将Reactor分成两部分,mainReactor负责监听server socket,accept新连接;并将建立的socket分派给subReactor。subReactor负责多路分离已连接的socket,读写网络数据,对业务处理功能,其扔给worker线程池完成。通常,subReactor个数上可与CPU个数等同。
利用主从NIO线程模型,可以解决一个服务端监听线程无法有效处理所有客户端连接的性能不足问题,因此,在Netty的官方Demo中,推荐使用该线程模型。
(4)Netty模型
Netty的线程模型并不是一成不变,它实际取决于用户的启动参数配置。通过设置不同的启动参数,Netty可以同时支持Reactor单线程模型、多线程模型和主从模型。
前面介绍完 Netty 相关一些理论,下面从功能特性、模块组件来介绍 Netty 的架构设计。
3. Netty功能特性
下图是Netty的功能特性:

4. Netty模块组件
Netty主要有下面一些组件:
- Selector
- NioEventLoop
- NioEventLoopGroup
- ChannelHandler
- ChannelHandlerContext
- ChannelPipeline
Selector
Netty 基于 Selector 对象实现 I/O 多路复用,通过 Selector 一个线程可以监听多个连接的 Channel 事件。
NioEventLoop
其中维护了一个线程和任务队列,支持异步提交执行任务,线程启动时会调用 NioEventLoop 的 run 方法,执行 I/O 任务和非 I/O 任务。
NioEventLoopGroup
主要管理 eventLoop 的生命周期,可以理解为一个线程池,内部维护了一组线程,每个线程(NioEventLoop)负责处理多个 Channel 上的事件,而一个 Channel 只对应于一个线程。
ChannelHandler
是一个接口,处理 I/O 事件或拦截 I/O 操作,并将其转发到其 ChannelPipeline(业务处理链)中的下一个处理程序。
ChannelHandlerContext
保存 Channel 相关的所有上下文信息,同时关联一个 ChannelHandler 对象。
ChannelPipeline 是保存 ChannelHandler 的 List,用于处理或拦截 Channel 的入站事件和出站操作。实现了一种高级形式的拦截过滤器模式,使用户可以完全控制事件的处理方式,以及 Channel 中各个的 ChannelHandler 如何相互交互。
ChannelPipeline对事件流的拦截和处理流程:

Netty中的事件分为Inbond事件和Outbound事件。
Inbound事件通常由I/O线程触发,如TCP链路建立事件、链路关闭事件、读事件、异常通知事件等。
Outbound事件通常是用户主动发起的网络I/O操作,如用户发起的连接操作、绑定操作、消息发送等。
在 Netty中,Channel 、ChannelHandler、ChannelHandlerContext、 ChannelPipeline的关系如下图:

一个 Channel 包含了一个 ChannelPipeline,而 ChannelPipeline 中又维护了一个由 ChannelHandlerContext 组成的双向链表,并且每个 ChannelHandlerContext 中又关联着一个 ChannelHandler。
入站事件和出站事件在一个双向链表中,入站事件会从链表 head 往后传递到最后一个入站的 handler,出站事件会从链表 tail 往前传递到最前一个出站的 handler,两种类型的 handler 互不干扰。
以上是Netty的主要原理介绍,Netty源码分析的话,后续有时间会继续分享出来。
Netty 基本原理的更多相关文章
- Netty通信原理
Netty是一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端,它极大的简化了TCP和UDP套接字服务器等网络编程. BIO(Blocking IO):每一个请求,一个S ...
- 这可能是目前最透彻的Netty原理架构解析
https://juejin.im/post/5be00763e51d453d4a5cf289 本文基于 Netty 4.1 展开介绍相关理论模型,使用场景,基本组件.整体架构,知其然且知其所以然,希 ...
- Netty原理架构解析
Netty原理架构解析 转载自:http://www.sohu.com/a/272879207_463994本文转载关于Netty的原理架构解析,方便之后巩固复习 Netty是一个异步事件驱动的网络应 ...
- 【Netty】最透彻的Netty原理架构解析
这可能是目前最透彻的Netty原理架构解析 本文基于 Netty 4.1 展开介绍相关理论模型,使用场景,基本组件.整体架构,知其然且知其所以然,希望给大家在实际开发实践.学习开源项目方面提供参考. ...
- dubbo在idea下的使用创建 服务者,消费者 注册中心
1.基于windows 下 spring 下的dubbo 需要书写配置文件 (1).创建带有web工程的项目 创建一个服务者 package cn.edu.aynu.bean; import lo ...
- 一个I/O线程可以并发处理N个客户端连接和读写操作 I/O复用模型 基于Buf操作NIO可以读取任意位置的数据 Channel中读取数据到Buffer中或将数据 Buffer 中写入到 Channel 事件驱动消息通知观察者模式
Tomcat那些事儿 https://mp.weixin.qq.com/s?__biz=MzI3MTEwODc5Ng==&mid=2650860016&idx=2&sn=549 ...
- Netty--索引
Netty 入门示例 Netty原理架构解析 Netty 基本原理 Netty面试题 阿里的Netty知识点你又了解多少
- dubbo入门学习(六)-----dubbo原理
RPC原理 一次完整的RPC调用流程(同步调用,异步另说)如下: 1)服务消费方(client)调用以本地调用方式调用服务: 2)client stub接收到调用后负责将方法.参数等组装成能够进行网络 ...
- 🏆【Alibaba微服务技术系列】「Dubbo3.0技术专题」回顾Dubbo2.x的技术原理和功能实现及源码分析(温故而知新)
RPC服务 什么叫RPC? RPC[Remote Procedure Call]是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范.它允许程序调用另一个地址空间(通常是共享网络的另 ...
随机推荐
- learning java 转换流
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public ...
- DOM内容梳理2
JavaScript-DOM2(内容整理) 这两天新的知识有点多有点杂一时半会没有整理过来,以后不出意外会一直更行. js节点类型(NODETYPE) 查看节点类型 nodetype属性,返回的结果会 ...
- “知乎杯”2018 CCF 大学生计算机系统与程序设计竞赛 贪心算法(greedy)
--> 贪心算法 1)题解 • 分别用V0.V1和V>=2表示度为0.1以及至少为2的顶点集合 • 对于每个顶点,维护三个属性: • degree ...
- Android程序员问答题
前言 最近三个月内,不断地进行移动应用开发在线测试题,也积累了不一样的知识.这也将对android studio有很好的掌握,对将来面试也很有好处.那么我就分享给大家.分享是一种幸福,这是一种质的飞越 ...
- 【DataStage】使用Sequence Job报错:CopyOfseq_ld..JobControl (fatal error from @Coordinator): Sequence job (restartable) will abort due to previous unrecoverable errors
错误描述: 在使用Sequence Job加载作业的时候,报了个错,详细错误内容如下: 出现这个错误的原因是由于以下配置问题,Excution action的状态为Run造成. 解决方案: 将Excu ...
- 懵了!简单的HTTP调用,时延竟如此大?
最近项目测试遇到个奇怪的现象,在测试环境通过 Apache HTTP Client 调用后端的 HTTP 服务,平均耗时居然接近 39.2ms. 图片来自 Pexels 可能乍一看觉得这不是很正常吗, ...
- JAVA学习网站分享
好久没用博客园了 最近工作不忙了,可以花时间自己学习知识提升自己,所以开始查找各种资料 java资源查找网站: http://www.java1234.com/ 前端学习网站: ...
- 第10组 Alpha冲刺(4/6)
链接部分 队名:女生都队 组长博客: 博客链接 作业博客:博客链接 小组内容 恩泽(组长) 过去两天完成了哪些任务 描述 学习调用中国天气网API,接近实现天气推送功能 对天气推送的形式进行讨论及重确 ...
- Research Guide for Neural Architecture Search
Research Guide for Neural Architecture Search 2019-09-19 09:29:04 This blog is from: https://heartbe ...
- Python Selenium Webdriver常用方法总结
Python Selenium Webdriver常用方法总结 常用方法函数 加载浏览器驱动: webdriver.Firefox() 打开页面:get() 关闭浏览器:quit() 最大化窗口: m ...