Netty 基本组件与线程模型
Netty 的学习内容主要是围绕 TCP 和 Java NIO 这两个点展开的,由于 Netty 是基于 Java NIO 的 API 之上构建的网络通讯框架,Java NIO 中的几个组件,都能在 Netty 中找到对应的封装。下面我们就来一一熟悉 Netty 中的基本组件。
一、基本组件
Netty 的组件主要有以下 8 个:
- Channel
- ByteBuf
- ChannelHandler
- ChannelHandlerContext
- Pipeline
- EventLoop
- EventLoopGroup
- ServerBootstrap/Bootstrap
1.1 Channel
Netty 中的 Channel 封装了 JDK 中原生的 Channel,所有对 Netty 中 Channel 的操作,最后都会转化成对原生 Channel 的操作。那么为什么要封装呢,主要有两点:1. 原生的 Channel 与 Netty 框架的结构不够兼容,所有 Netty 进行了一层包装,使其更符合 Netty 使用逻辑;2. 避免了对 SocketChannel 的直接操作,提供更直观和友好的 API 给开发人员。
Netty 常用的是 NioSocketChannel 和 NioServerSocketChannel,对应了 JDK 中的 SocketChannel 和 ServerSocketChannel。Netty 中的 Channel 都有与之对应的 EventLoop 和 Pipeline。
1.2 ByteBuf
ByteBuf 与 JDK 中的 ByteBuffer 类似。Netty 中的 ByteBuf 有基于 ByteBuffer 构建的,也有自身设计的其他实现。从不同的层级可以有多种划分方式,使用时主要关注的可能这 3 个方面:1. 池化与非池化;2. 堆内存与直接内存;3. 是否使用了 Unsafe 类来操作内存。关于这几点暂时有个大致的了解即可。
ByteBuffer 只使用一个指针来保存读写的索引,使用起来比较麻烦,容易出错。而 ByteBuf 则使用了两个指针分别保存当前读和写的索引,使用起来就很方便,从 ByteBuf 读取数据时,只需要关注 readerIndex 即可。将数据写入 ByteBuf 时,只需要关注 writerIndex。ByteBuff 的容量 capacity 与两个指针之间的大小关系:0 <= readerIndex <= writerIndex <= capacity。
Netty 源码中 ByteBuf 的类注释很好的展示了它的结构:
/*
* +-------------------+------------------+------------------+
* | discardable bytes | readable bytes | writable bytes |
* | | (CONTENT) | |
* +-------------------+------------------+------------------+
* | | | |
* 0 <= readerIndex <= writerIndex <= capacity
*/
1.3 ChannelHandler
ChannelHandler 简言之就是一个处理器, 它的功能就是处理消息。它就像流水线上的工人,对每一个从他面前经过的部件进行加工。与工人稍有不同的地方是,它可以什么也不做,将消息直接交给下一个处理器,也可以直接将消息丢掉,不再传递。而且 ChannelHandler 是有方向的。对于开发人员来说,就是在 ChannelHandler 中编写业务逻辑代码,需要注意的是在 Handler 中不要执行耗时较大的业务逻辑,避免影响 IO。
1.4 ChannelHandlerContext
从名称即可知道它是 ChannelHandler 的容器,每个 ChannelHandler 都有与之一一对应的 ChannelHandlerContext 对应。实际上,每个 ChannelHandler 并不直接交互,都是通过 ChannelHandlerContext 将彼此联系起来。ChannelHandlerContext 则是一个 Node,它有前驱和后继。对于一个 Channel 来说,它看到的是一个双向链表。
1.5 Pipeline
Pipeline 中保存了由 ChannelHandlerContext 组成的双向链表。Netty 中的每个 Channel 都有一条自己的 Pipeline,每当该通道有需要处理的消息时,就会遍历 Pipeline 中的链表,通过每一个处理器来处理消息。Pipeline 的链表中默认就保存了一个 Head 和一个 Tail,所有用户添加的处理器都在这两个节点之间。下图就是包含一个用户处理器的 Pipeline:
1.6 EventLoop
EventLoop 可以简单的看作是一个线程,用来处理分配给它的 Channel 上的事件,也就是说一个 EventLoop 下面可能挂了多个 Channel。
1.7 EventLoopGroup
从它的名称就可以知道它维护了一组 EventLoop,可以看作是一个 Netty 实现的线程池,负责给每一个新建里的 Channel 分配 EventLoop。
1.8 ServerBootstrap/Bootstrap
这两个组件分别是用来启动服务端和客户端 ,在启动之前,可以通过这两个组件设定各种参数,添加 Handler,指定通道类型等。(Bootstrap 是鞋带的意思,为啥跟启动挂上勾了,可以参考知乎上的解答:Boot一词是为什么被用作计算机并作为引导解释的?或者说他的由来? - 知乎)
二、Netty 线程模型
Netty 采用的是 Reactor 线程模型,先从一个最简单的 HelloWorldServer 级别的线程模型来入手,如下图:
先了解一个 Channel 的建立过程:
- 服务端启动时,会启用一个线程并创建一个 NioServerSocketChannel 来监听指定的端口。这个线程上有一个 Selector,它关注的是 Accpet 事件;
- 当有客户端连接过来时,上图中的 EventLoop-0会创建一个 NioSocketChannel ,将该通道注册到 EventLoop-1 的 Selector 上,然后 EventLoop-1 就负责此后该 Channel 生命周期上所有的读写事件的处理;
- EventLoop-1 对其所属通道数据读写及其他处理,就通过 Pipeline 中的处理器链来实现。
Netty 还包含了普通任务和定时任务的执行。
参考资料:
- 『Netty 实战』- 中文版
- 『Netty 权威指南』- 第二版,这本书是基于 Netty 5 写的,虽然 Netty 5 项目已经关闭了,但是本书还是值得参考的
- Java读源码之Netty深入剖析-慕课网实战 - 基本上对源码的分析和了解,都是基于这个视频课程的内容,讲的挺好的
Netty 基本组件与线程模型的更多相关文章
- 【Netty】EventLoop和线程模型
一.前言 在学习了ChannelHandler和ChannelPipeline的有关细节后,接着学习Netty的EventLoop和线程模型. 二.EventLoop和线程模型 2.1. 线程模型 线 ...
- Netty高性能之Reactor线程模型
Netty是一个高性能.异步事件驱动的NIO框架,它提供了对TCP.UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用 ...
- 一文弄懂-Netty核心功能及线程模型
目录 一. Netty是什么? 二. Netty 的使用场景 三. Netty通讯示例 1. Netty的maven依赖 2. 服务端代码 3. 客户端代码 四. Netty线程模型 五. Netty ...
- Netty学习三:线程模型
1 Proactor和Reactor Proactor和Reactor是两种经典的多路复用I/O模型,主要用于在高并发.高吞吐量的环境中进行I/O处理. I/O多路复用机制都依赖于一个事件分发器,事件 ...
- 深入了解Netty【五】线程模型
引言 不同的线程模型对程序的性能有很大的影响,Netty是建立在Reactor模型的基础上,要搞清Netty的线程模型,需要了解一目前常见线程模型的一些概念. 具体是进程还是线程,是和平台或者编程语言 ...
- Netty源码学习(一)Netty线程模型
给你一台4路E7-4820V2(32核心64线程),512G内存的服务器,你该如何编程才能支持百万长连接? 最直接的想法是采用BIO的模式,为每个连接新建一个线程,在一一对应的线程中直接处理连接上的数 ...
- Reactor 线程模型以及在netty中的应用
这里我们需要理解的一点是Reactor线程模型是基于同步非阻塞IO实现的.对于异步非阻塞IO的实现是Proactor模型. 一 Reactor 单线程模型 Reactor单线程模型就是指所有的IO操作 ...
- 深入Netty逻辑架构,从Reactor线程模型开始
本文是Netty系列第6篇 上一篇文章我们从一个Netty的使用Demo,了解了用Netty构建一个Server服务端应用的基本方式.并且从这个Demo出发,简述了Netty的逻辑架构,并对Chann ...
- Netty源码分析之Reactor线程模型详解
上一篇文章,分析了Netty服务端启动的初始化过程,今天我们来分析一下Netty中的Reactor线程模型 在分析源码之前,我们先分析,哪些地方用到了EventLoop? NioServerSocke ...
随机推荐
- CentOS7系统系统检查脚本
#!/bin/bash ############################################################## # File Name: .sh # Versio ...
- uva 10288 gailv
Problem F Coupons Input: standard input Output: standard output Time Limit: seconds Memory Limit: MB ...
- 学号 2018-2019-20175212 童皓桢《Java程序设计》第5周学习总结
学号 2018-2019-20175212 <Java程序设计>第5周学习总结 教材学习内容总结 接口 声明接口: interface 名字: 接口体:接口体中只有常量无变量,只有抽象方法 ...
- mysql实现随机获取几条数据的方法
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/xionglangs/article/details/50630758sql语句有几种写法 1:SEL ...
- CentOS 7系统上添加netcdf库
这里提供两种方法来安装 netcdf: 一是 yum 安装,yum 安装时采用的是系统自带的 gfortran 编译器,版本较旧: 二是采用源码来 Makefile 编译安装的方式,它可以下载最新版的 ...
- 【密码技术】Part 4 SSL/TLS
01 SSL/TLS基本概念 02 TLS协议流程图
- 利用this属性实现点击按钮变色.选中效果
浏览器宿主的全局环境中,this指的是window对象. <script type="text/javascript"> console.log(this === wi ...
- 8款非常不错的.Net反编译利器
本人搜集了下8款非常不错的.Net反编译利器: 1.Reflector Reflector是最为流行的.Net反编译工具.Reflector是由微软员工Lutz Roeder编写的免费程序.Refle ...
- Android最火热修复实战
Sophix官网文档地址 https://help.aliyun.com/document_detail/53240.html 快速接入 项目build.gradle的repositories节点下添 ...
- IE浏览器下flex布局的bug
原文地址:gitub上的Flexbugs list,可以看到Flex布局在IE糟糕表现的详细描述. 2. Column flex items set to align-items:center ove ...