您当前的位置: 首页 > 

水的精神

暂无认证

  • 1浏览

    0关注

    711博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

用脑图构建netty知识脉络

水的精神 发布时间:2021-06-25 05:07:57 ,浏览量:1

这张脑图整理自《netty实战》

其中书中的知识点都有覆盖到,书中的netty使用案例没有整理出来。

Netty实战
	Netty是什么?
		是一款用于创建高性能网络应用程序的高级框架
		异步的
		事件驱动的
	主要构件
		Channel
			Java NIO的基本构造
			数据传入或传出的载体
			可以打开、关闭
			可以连接、断开连接
			Netty内部为每个Channel分配了一个EventLoop
		回调
			一个方法
			这个方法的引用提供给另一个方法,以便后者在适当的时机调用前者
			作用
				通常在操作完成后通知相关方
				Netty使用回调处理事件
		Future
			同样可用作通知
				方法1调用方法2,方法2将耗时操作交给线程处理,并立刻返回一个Future占位符,方法1可以继续干活,并在将来使用Future得到方法2交给线程处理后的真正执行结果
				弊端
					get()之前需要手动检测是否完成
					或者直接get(),这将会一直阻塞到真正的操作完成
			Netty的改进
				ChannelFuture
					增加了监听器,在真正操作完成时,自动获得通知
						ChannelFutureListener
						operationComplete()
					Future和回调相辅相成,通常一起使用
		事件和ChannelHandler
			事件可触发的动作
				记录日志
				数据转换
				流控制
				应用程序逻辑
				......
			入站事件
				连接激活或失活
				数据读取
				用户事件
				错误事件
				......
			出站事件
				将数据写到或者冲刷套接字
				打开或关闭远程节点的连接
				......
			ChannelHandler可看作是为相应特定事件而被执行的回调
			一组ChannelHandler事件处理器构成一条链
				事件->处理器->事件->处理器->->->->
				Netty提供了大量预定义的ChannelHandler实现
					HTTP
					SSL/TLS
					......
	Netty的传输方式
		NIO
			基于java.nio.channels包,基于选择器的方式
				零拷贝
					数据直接从文件系统移动到网络接口
					而不需要从内核空间复制到用户空间
		Epoll
			仅Linux支持
			比NIO传输更快,完全非阻塞
				支持零拷贝
		OIO
			基于java.net (http://java.net)包,使用阻塞流
				SO_TIMEOUT超时抛出异常,从而继续处理循环
		Local
			在VM内部通过管道进行通信的本地传输
			不需要暴露网络
		Embedded
			常用于单元测试ChannelHandler
			不需要真实的基于网络的传输,可用于测试ChannelHandler
			可以将一组ChannelHandler嵌入到其他的ChannelHandler内部,从而扩展一个CH的功能,而不需要修改其内部代码
	ByteBuf
		是什么?
			Netty的数据容器
			作为JavaNIO提供的ByteBuffer替代品
				功能更多
				使用更加简单方便
		优点
			可被用户自定义的缓冲区类型扩展
			通过内置的复合缓冲区类型实现了透明的零拷贝
			容量可按需增长
			读和写切换不需要调用ByteBuffer的flip()方法
			读和写使用不同的索引
				试图读超出写入的长度数据,将会溢出异常
				可以指定ByteBuf的最大容量,默认时Integer.MAX_VALUE
					写索引超出也会溢出异常
			支持方法的链式调用
			支持引用计数
			支持池化
		使用模式
			堆缓冲区(支撑数组)
				适合有遗留数据需要处理的情况
				存储在JVM的堆空间中
				提供快速的分配和释放
			直接缓冲区
				不被GC回收
				分配和释放较为昂贵
				多一次复制到堆
			复合缓冲区
				CompositeByteBuf
				提供一个聚合视图,方便管理
		字节级操作
			随机访问索引
				getByte(i)
			顺序访问索引
			可丢弃字节
				0~readIndex
					read后即可丢弃
						write会增加writeIndex
					get不会增加readIndex
						set不会增加writeIndex
				丢弃后,readIndex变为0,writeIndex也会变少
			可读字节
				buffer.isReadable()
			可写字节
				buffer.writableBytes()
			索引管理
				mark
				reset
				clear
					同时清零
			查找操作
				int index = buffer.forEachByte(ByteBufProcessor.FIND_CR);
					FIND_CR
					FIND_NULL
				查找值的索引
			派生缓冲区
				返回新的ByteBuf实例
				但共享了原始ByteBuffer
				因此创建成本低廉
				但改变了派生缓冲区,也将改变原始缓冲区
				派生方法
					duplicate()
					slice()
					slice(int,int)
					Unpooled.unmodifiableBuffer(...)
					order(ByteOrder)
					readSlice(int)
				非派生方法
					copy()
						产生了独立的真实缓冲区的副本
			读/写操作
				write\read
					改变index
				set\get
					不改变index
			更多的操作
				capacity()
					返回当前可容纳的字节数
						可扩展
				maxCapacity()
					返回最大可容纳的字节数
		ByteBufHolder
			用于缓冲区池化,从池中借用ByteBuf
			在需要时自动释放
			三个主要方法
				content()
					返回该ByteBufHolder所持有的ByteBuf
				copy()
					返回这个ByteBufHolder的一个深拷贝,包括一个其所包含的ByteBuf的非共享拷贝
				duplicate()
					返回这个ByteBufHolder的一个浅拷贝,包括一个其所包含的ByteBuf的共享拷贝
		ByteBuf分配
			ByteBufAllocator
				池化的
				按需分配
				支持操作
					buffer()
						返回一个基于堆或者直接内存存储的ByteBuf
					heapBuffer()
						返回一个基于堆内存存储的ByteBuf
					directBuffer()
						返回一个基于直接内存存储的ByteBuf
					compositeBuffer()
						compositeHeapBuffer()
						compositeDirectBuffer()
					ioBuffer()
						返回一个用于套接字的I/O操作的 ByteBuf
			Unpooled缓冲区
				未池化的
				支持操作
					buffer()
						未池化的基于堆
					directBuffer()
						未池化的基于直接内存
					wrappedBuffer()
						包装了给定数据的
					copiedBuffer()
						复制了给定数据的
			ByteBufUtil
				最常用方法
					hexdump()
						十六进制打印ByteBuf
					equals()
						比较ByteBuf实例
		引用计数
			对象的活动引用的数量
			引用数量为0的实例会被释放
				池化实例释放的依据
			buffer.release()
				返回该对象是否被释放
	ChannelHandler和ChannelPipeline
		Channel状态
			已创建,未注册到EventLoop
				ChannelUnregistered
			已注册到EventLoop
				ChannelRegistered
			处于活动状态(已连接到它的远程节点),可收发数据了
				ChannelActive
			没有连接到远程节点
				ChannelInactive
		ChannelHandler的生命周期
			被添加到ChannelPipeLine中
				handlerAdded
			从ChannelPipeLine中移除
				handlerRemoved
			在ChannelPipeLine中发生异常
				exceptionCaught
		ChannelInboundHandler接口
			channelRead
				从channel读数据时调用
			channelComplite
				读完成时调用
			channelWritability
				channel可写状态改变时调用
		ChannelOutboundHandler接口
			bind()
				将channel绑定到本地地址
			connect()
				将channel连接到远程节点
			disconnect()
				请求将channel从远程节点中断开
			close()
				请求关闭channel时调用
			deregister()
				请求将channel从EventLoop中注销时调用
			read()
				读数据时
			flush()
				通过channel将入队数据冲刷到远程节点
			write()
				通过channel将数据写到远程节点
		ChannelHandler适配器
			ChannelInboundHandlerAdapter
				SimpleChannelInboundHandler
			ChannelOutboundHandlerAdapter
		资源泄漏保护
			ResourceLeakDetector
			泄漏检测级别
				DISABLED
				SIMPLE
				ADVANCED
				PARANOID
					消耗大,只在调试阶段使用
		ChannelPipeline
			管理操作
				add*()
					入站在头部
						入站时经过
							ChannelInboundHandler
								1->2->3->...
							而不会经过ChannelOutboundHandler
					出站在尾部
						出站时经过
							ChannelOutboundHandler
								6->5->4->...
							而不会经过ChannelInboundHandler
				remove()
				replace()
			访问操作
				get()
					通过名称或者类型返回ChannelHandler
				context()
					返回和 ChannelHandler绑定的ChannelHandlerContext
				names()
					返回所有ChannelHandler的名称
			触发事件
				入站操作
					 fire*()
				出站操作
					writeAndFlush()
					......
		ChannelHandlerContext
			每向pipline中添加一个channelhandler就会创建一个context
				调用方法时,只会传播给此context当前关联的ChannelHandler的下一个处理该事件的ChannelHandler
					而Channel和pipeline是会沿着整个pipeline传播
			具有丰富的处理事件和执行IO操作的API
			可让ChannelHandler与它的pipeline以及其他ChannelHandler交互
			操作
				pipeline()
				writeAndFlush()
				name()
				handler()
				......
			意义
				减少将事件传经对它不感兴趣的ChannelHandler所带来的开销
				避免将事件传经那些可能会对它感兴趣的ChannelHandler
		高级应用
			动态切换协议
		异常处理
			处理入站异常
				exceptionCaught
					默认转发给pipeline的下一个handler,直到最后没被处理的话会被标记为未处理
					可重写处理异常,如不往下抛异常等
			处理出站异常
				基于通知机制
					每个出站操作都将返回一个ChannelFuture
					ChannelPromise是ChannelFuture的一个子类
						几乎每一个出站方法都传入了一个ChannelPromise
						可被分配用于异步通知的监听器
						也可以提供立即通知的可写方法
							setSuccess()
							setFailure(Throwable cause)
					addListener(ChannelFutureListener)的时机
						方法1
							在每次write后返回的future中添加
								优点
									可共享调用者的属性和方法等
						方法2
							在ChannelHandler的write方法中,统一添加
								优点
									一次编写,到处可用
	EvenLoop和线程模型
		线程模型概述
			使用线程池
				从池中得到一个空闲的Thread去执行一个Runnable实例任务
				用完后放回池中
				减少线程创建和销毁开销
		EventLoop
			while(!terminated)
			List readyEvents = blockUntilEventsReady();
				阻塞,直到有事件已经就绪可被运行
			for (Runnable ev: readyEvents) {
   ev.run();
 }
				循环遍历,并处理所有的事件
			一个EventLoop可用于服务多个Channel
			优化
		任务调度
			ScheduledExecutorService
				延迟之后运行或者周期性地执行任务
					schedule()
					scheduleAtFixedRate()
				取消任务
					future.cancel()
				线程池方式
				单线程方式
		实现细节
			如果是EventLoop中的事件,则立即执行
			否则加入队列,提交到线程池执行
		EventLoop线程分配
			非阻塞
				一个EventLoop占用一个线程
				一个线程管理多个Channel
			阻塞
				一个EventLoop占用一个线程
				一个线程管理一个Cahnnel
	Bootstrap引导
		是什么?
			如何对应用程序进行配置,将各个部分组织起来,让应用程序运行起来的过程
		两种引导
			BootStrap
				为客户端和使用无连接协议的应用程序创建Channel
				bind()用于无连接协议(UDP)
					DatagramChannel
					用于收发数据包
						无法得知发送的数据是否被接收成功
			ServerBootStrap
				方法
					handler()
						此方法添加的ChannelHandler由ServerChannel(此为用于接受子Channel的Channel)处理
							bind()创建了ServerChannel
							ServerChannel管理了很多子连接的Channel
					childHandler()
						此方法添加的ChannelHandler由已被接受的子Channel处理
						更常用
					option()
						用于配置Channel-Option,通过bind()方法设置到Channel
							如配置5秒连接超时
								bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS,5000)
									
								SO_TIMEOUT 只对于 OIO有效,对于NIO 没有作用,用于超时控制
						bind()后修改option无效
					childOption()
						更常用
					attr()
						用于指定ServerChannel上的属性,方便使用
					childAttr()
						更常用
				一些常见应用
					在子Channel中引导BootStrap客户端
						
						通过共享Channel的EventLoop来避免新增EventLoop线程产生资源浪费
							bootstrap.group(channel.eventLoop())
					在引导过程中添加多个ChannelHandler
						ChannelInitializerImpl extends ChannelInitializer
							重写initChannel()
							在initChannel()中添加ChannelHandler
								channel.pipeline().addLast(channel handler)
						serverbootstrap.childHandler(new ChannelInitializerImpl())
					优雅的关闭应用程序
						释放所有的资源,并且关闭所有的当前正在使用中的Channel
						group.shutdownGracefully().sync();
		EventLoop和Chanel不能混用NIO和OIO
	网络协议
		WebSocket
			新版浏览器基本都支持WebSocket,WS是HTML5的一部分
			可通过HTTP协议进行WebSocket协议握手
				在协议升级后即可通过WebSocket传输消息
			特点
				双向
				异步
				实时
			应用
				WEB版聊天室
				......
		TCP
			优点
				有序
				安全
			缺点
				较UDP慢
		UDP
			缺点
				无序,可能丢包
				不安全
			优点
				传输快
					无需握手确认
					无需反馈
				支持多播
					传输到一个预定义的主机组
				支持广播
					传输到网络(或子网)上的所有主机
			成员
				广播者
					Broadcaster
				监听者
					Monitor
			应用
				日志广播
				视频传输
				......

关注
打赏
1664074814
查看更多评论
立即登录/注册

微信扫码登录

0.0375s