Netty知识点总结
2021-11-01 14:57:41 1 举报
AI智能生成
登录查看完整内容
为你推荐
查看更多
Netty知识点总结
作者其他创作
大纲/内容
强调进程/线程要访问的数据是否就绪,进程/线程是否需要等待,强调的数据准备这个过程;
非阻塞 vs 阻塞
同步和异步:同步和异步一般是面向操作系统与应用程序对IO操作的层面上来区别的。
访问数据的方式,同步需要主动读写数据,在读写数据的过程中还是会阻塞;异步只需要I/O操作完成的通知,并不主动读写数据,由操作系统内核完成数据的读写,强调I/O真正读写这个阶段。
同步/异步
阻塞 IO
非阻塞 IO
多路复用
异步 IO
阻塞 IO vs 多路复用
1.IO 模型
数据的读取写入必须阻塞在一个线程内等待其完成线程数量:客户端并发访问数为1:1,由于线程是Java虚拟机中非常宝贵的资源,一旦线程数急剧增加,系统性能会急剧下降,导致线程栈溢出,创建新的线程失败,并最终导致宕机
1.BIO(同步阻塞IO)
用NIO方式处理IO使用多路复用器Selector来轮询每个通道Channel,当通道中有事件时就通知处理,不过使用起来相当复杂。
channel它就是读写数据的**双向通道**,可以从 channel 将数据读入 buffer,也可以将 buffer 的数据写入
Channel
与Channel进行交互,数据是从Channel读入缓冲区,从缓冲区写入Channel中的
Buffer(缓冲区)
Selector(选择器、多路复用器)
三大组件
2.NIO(同步非阻塞IO)
3.AIO(真正的异步非阻塞IO)
图片
流程
传统 IO 问题
NIO 优化
4.零拷贝
2. NIO vs BIO vs AIO
1. NIO基础
Netty是基于Java NIO client-server的网络应用框架,使用Netty可以快速开发网络应用。Netty的内部实现是很复杂的,但是Netty提供了简单易用的API从网络处理代码中解耦业务逻辑。Netty是完全基于NIO实现的,所以整个Netty都是异步的。
高并发、传输快、封装好
特点
使用简单、功能强大、定制能力强、性能高、稳定、社区活跃
优势
同步非阻塞、用更少的资源干更多的事
IO线程模型(IO多路复用)
不需要将buffer从一个内存区域移动到另一个内存区域
从OS角度:避免在用户态和内核态之间拷贝数据
ByteBuf 支持 font color=\"#f15a23\
通过 FileRegion 包装的FileChannel.font color=\"#f15a23\
对于 Netty ByteBuf 的零拷贝(Zero Copy) 的理解
内存零拷贝
申请的内存可以重复使用(直接内存)
内部通过一个二叉查找树管理内存分配情况
内存池设计
避免使用锁带来的性能开销
串行化处理读写
支持protobuf等高性能序列化协议
高性能序列化协议
高性能原因
默认情况下Netty启动CPU 处理器两倍的线程,bind 完之后启动。
eaderIdleTime:为读超时时间(即测试端一定时间内未接受到被测试端消息)。
writerIdleTime:为写超时时间(即测试端一定时间内向被测试端发送消息)。
allIdleTime:所有类型的超时时间。
支持的心跳类型
1.Netty 是什么
流程梳理
代码
服务器端
客户端
Netty执行大致流程
2. 开发一个简单的服务器端和客户端
所有操作都在同一个NIO线程处理,在这个单线程中要负责接收请求,处理IO,编解码所有操作,相当于一个饭馆只有一个人,同时负责前台和后台服务,效率低。
单线程模型
有一个NIO 线程(Acceptor)接收客户端的TCP 连接请求,一组线程池负责网络IO 的操作,即消息的读取、解码、编码和发送;相当于一个饭馆有一个前台负责接待,有很多服务员去做后面的工作,这样效率就比单线程模型提高很多。
多线程模型
一组线程(Acceptor) 负责接收客户端的TCP 连接请求;一组线程负责网络IO 的操作,即消息的读取、解码、编码和发送;
主从多线程模型
netty中的具体运用:基于多路复用器接收并处理用户请求,内部实现了两个线程池,boss线程池和work线程池,boss线程池的线程负责处理请求的accept事件,当接收到accept事件的请求时,把对应的socket封装到一个Channel中,并交给work线程池,work线程池负责请求的read和write事件,由对应的Handler处理
Netty采用了第三种模型:主从线程模型
3.reactor线程模型
EventLoop 本质是一个单线程执行器(同时维护了一个 Selector),里面有 run 方法处理 Channel 上源源不断的 io 事件。
EventLoop(事件循环对象)
包含一个或多个EventLoop
EventLoopGroup 是一组 EventLoop,Channel 一般会调用 EventLoopGroup 的 register 方法来绑定其中一个 EventLoop,后续这个 Channel 上的 io 事件都由此 EventLoop 来处理(保证了 io 事件处理时的线程安全)
EventLoopGroup(事件循环组)
socket
一个channel在生命周期内只注册一于个EventLoop
异步通知
Netty 框架中所有的 I/O 操作都为异步的,因此我们需要 ChannelFuture 的 addListener()注册一个 ChannelFutureListener 监听事件,当操作执行成功或者失败时,监听就会自动触发返回结果
ChannelFuture
所有处理入站和处理出站数据的应用程序逻辑的地方
主要用来处理各种事件,这里的事件很广泛,比如可以是连接、数据接收、异常、数据转换等
ChannelHandler
提供了ChannelHandler 链的容器,并定义了用于在该链上传播入站和出站事件流的API
ChannelPipeLine
当ChannelHandler 被添加到ChannelPipeline 时,它将会被分配一个ChannelHandlerContext,其代表了ChannelHandler 和ChannelPipeline 之间的绑定
ChannelHandlerContext
Netty 的ByteBuffer 替代品是ByteBuf,一个强大的实现,既解决了JDK API 的局限性,又为网络应用程序的开发者提供了更好的API。
ByteBuf 维护了两个不同的索引,名称以read 或者write 开头的ByteBuf 方法,将会推进其对应的索引,而名称以set 或者get 开头的操作则不会
堆缓冲区
直接缓冲区
复合缓冲区
使用
随机访问/顺序访问/读写操作
可丢弃字节/可读字节/可写字节
索引管理
查找操作
派生缓冲区
引用计数
概念及API
零拷贝技术
支持自动扩容(4M),保证put方法不会抛出异常、通过内置的复合缓冲类型,实现零拷贝(zero-copy);不需要调用flip()来切换读/写模式,读取和写入索引分开;方法链;引用计数基于AtomicIntegerFieldUpdater用于内存回收;PooledByteBuf采用二叉树来实现一个内存池,集中管理内存的分配和释放,不用每次使用都新建一个缓冲区对象。UnpooledHeapByteBuf每次都会新建一个缓冲区对象。
ByteBuf
4. 组件
2. Netty 入门
Java序列化的目的主要有两个:1.网络传输。2.对象持久化。
Java序列化的缺点:1.无法跨语言。 2.序列化后码流太大。3.序列化性能太低。
Protobuf全称Google Protocol Buffers,它由谷歌开源而来,在谷歌内部久经考验。它将数据结构以.proto文件进行描述,通过代码生成工具可以生成对应数据结构的POJO对象和Protobuf相关的方法和属性
Google的Protobuf
Protostuff是基于大名鼎鼎的Google protobuff技术的Java版,它较于protobuf最明显的好处是,在几乎不损耗性能的情况下做到了不用我们写.proto文件来实现序列化。Protostuff反序列化时并不要求类型匹配,比如包名、类名甚至是字段名,它仅仅需要序列化类型A 和反序列化类型B 的字段类型可转换(比如int可以转换为long)即可
Protostuff
Thrift源于Facebook,Thrift可以支持多种程序语言,如C++、C#、Cocoa、Erlang、Haskell、Java、Ocami、Perl、PHP、Python、Ruby和Smalltalk。在多种不同的语言之间通信,Thrift可以作为高性能的通信中间件使用,它支持数据(对象)序列化和多种类型的RPC服务。Thrift适用于静态的数据交换,需要先确定好它的数据结构,当数据结构发生变化时,必须重新编辑IDL文件,生成代码和编译,这一点跟其他IDL工具相比可以视为是Thrift的弱项。Thrift适用于搭建大型数据交换及存储的通用工具,对于大型系统中的内部数据传输,相对于JSON和XML在性能和传输大小上都有明显的优势。
Apache的Thrift
JBoss Marshalling是一个Java对象的序列化API包,修正了JDK自带的序列化包的很多问题,但又保持跟java.io.Serializable接口的兼容;同时增加了一些可调的参数和附加的特性,并且这些参数和特性可通过工厂类进行配置。
JBoss Marshalling
Hadoop的一个子项目,解决了JSON的冗长和没有IDL的问题
支持丰富的数据类型、简单的动态语言结合功能、具有自我描述属性、提高了数据解析速度、快速可压缩的二进制数据形式、可以实现远程过程调用RPC、支持跨编程语言实现
优点
对于习惯于静态类型语言的用户不直观
缺点
在Hadoop中做Hive、Pig和MapReduce的持久化数据格式
适用场景
Avro
一个高效的二进制序列化格式
Message pack
采用二进制协议的轻量级remoting onhttp工具
Hessian
kryo
其他序列化框架
Java序列化
负责将消息从字节或其他序列形式转成指定的消息对象
编码器
将字节解码为消息
将一种消息类型解码为另一种
TooLongFrameException
解码器
1.编解码技术
短连接
固定长度
固定分隔符
预设长度
解决方案
应用程序写入数据的字节大小大于套接字发送缓冲区的大小进行MSS大小的TCP分段以太网的payload大于MTU进行IP分片
原因
FixedLengthFrameDecoder类
1.消息定长,例如每个报文的大小为固定长度200字节,如果不够,空位补空格。
行分隔符类:LineBasedFrameDecoder
自定义分隔符类 :DelimiterBasedFrameDecoder
2.报文 尾增加特殊字符分割,例如FTP协议。
LengthFieldBasedFrameDecoder类。分为有头部的拆包与粘包、长度字段在前且有头部的拆包与粘包、多扩展头部的拆包与粘包。
3.将消息分为消息头和消息体,消息头中包含表示消息总长度(或者消息体长度)的字段,通常设计思路为消息头的第一个字段使用int32来表示消息的总长度。
解决方式
2.Netty之TCP粘包/拆包
为什么需要协议
编解码器
@Sharable
自定义协议要素
自定义协议
3. 协议设计与解析
服务发布与订阅:服务端使用Zookeeper注册服务地址,客户端从Zookeeper获取可用的服务地址。通信:使用Netty作为通信框架。Spring:使用Spring配置服务,加载Bean,扫描注解。动态代理:客户端使用代理模式透明化服务调用。消息编解码:使用Protostuff序列化和反序列化消息。
设计思路
4.实现一个轻量级分布式RPC框架
nginx或haproxy做集群TCP负载均衡,用户session信息存到redis
TCP连接负载均衡
服务端向客户端上传消息时保存ChannelHandlerContext到内存,下发消息时所有的服务器都推送一遍
服务端向客户端发送TCP消息
5.TCP连接之负载均衡和双向通信
3. Netty 进阶
1. 启动流程剖析
2.EventLoop 剖析
3. accept 流程剖析
4. read 流程剖析
4. Netty 源码
Netty
0 条评论
回复 删除
下一页