共计 2054 个字符,预计需要花费 6 分钟才能阅读完成。
ButeBuf
1.ByteBuffer 的缺点
长度固定,容量不能动态扩展、收缩,遇到大的 POJO 会出现索引越界异常
只有一个标识指针 position,需要手动调用 flip 和 rewind
2. 实现策略
基于 JDK ByteBuffer,增加额外的功能,解决原有 ByteBuffer 的缺点
聚合 JDK ByteBuffer,通过 Facade 模式对其进行包装,可以减少自身的代码量,降低实现成本
3. 读写操作
读操作使用 readerIndex、写操作使用 writerIndex
4. 自动扩容
put 操作对剩余空间进行校验,不足则创建新的 ByteBuffer,并对之前的 ByteBuffer 复制到新创建的 ByteBuffer,释放 ByteBuffer
5. 内存分类
堆内存(HeapByteBuf):内存的分配和回收速度快,可以被 JVM 自动回收,缺点:进行 Socket 的 I / O 读写,需要额外复制一次,将堆内存对应的缓冲区复制到内核 Channel
直接内存(DirectByteBuf):非堆内存,相比堆内存,他的分配和回收速度会慢一些,但是将他写入 socket,由于少了一次内存复制,速度比堆内存快
6. 最佳实践
在 I / O 通信线程的读写缓冲区使用 DirectByteBuf,后端业务消息的编解码模块使用 HeapByteBuf,可以达到性能最优
注意:推荐使用基于内存的 ByteBuf,但是内存池的管理和维护更加复杂,使用起来需要谨慎
Channel 和 Unsafe
1.Channel
Netty 自己的 Channel,用于异步 I / O 操作和其他相关的操作
2.Unsafe
内部接口,聚合在 Channel 中协助进行网络读写的相关操作,不应该被上层使用者调用
3.Channel 设计理念
采用 Facade 模式进行统一封装,将网络 I / O 操作等封装,统一对外提供
接口定义大而全,提供与 socketchannel、serversocketchannel 统一的视图,由不同的子类实现不同的功能,公共功能在抽象父类中实现,最大程度地实现功能和接口的重用
采用聚合而非包含的方式,统一负责分配和调度
4.Unsafe 功能
I/ O 读写操作由其完成
ChannelPipeline 和 ChannelHandler
其类似 Servlet 和 Filter 过滤器,这类拦截器实际上式职责链模式的一种变形,主要是为了方便事件的拦截和用户业务逻辑的定制
1.ChannelPipeline 主要特性
支持运行态动态的添加 / 删除 ChannelHandler,如业务高峰进行拥塞保护 ChannelHandler 的添加,高峰期结束后则删除
ChannelPipeline 是线程安全的,不存在多线程并发问题,但是 ChannelHandler 不是线程安全,用户需要保证自己的 ChannelHandler 线程安全
2.ChannelHandler 功能说明
负责 I / O 事件或者 I / O 操作进行拦截和处理,它可以选择性地拦截和处理自己感兴趣的事件,也可以透传和终止事件的传递
3.ChannelHandler 分类
Pipeline 系统的,用户不可预见,HeadHandler、TailHandler
编解码 Handler
系统功能性,流量整型 Handler、读写超时 Handler、日志 Handler
EventLoop 和 EventLoopGroup
1.Reactor 单线程模型
所有 I / O 操作都在同一个 NIO 线程上完成(异步非阻塞)
面对高负载、大并发不合适
(1)性能无法支撑
(2)负载过重,处理速度变慢,导致消息积压和处理超时,成为系统瓶颈
(3)可靠性问题,一坏就全坏
2.Reactor 多线程模型
比起单线程,多出一组 NIO 线程来处理 I / O 操作
一个 NIO 处理 Acceptor 线程监听服务端,接受客户端的连接请求
网络操作读写由一个 NIO 线程池处理,采用标准的 JDK 线程池,一个任务队列和 N 个线程
一个 NIO 线程处理多条连理,一个链路只对应一个 NIO 线程
3. 主从 Reactor 多线程模型
服务端接收客户端连接是一个独立的 NIO 线程池
可以解决一个服务端监听线程无法有效处理所有客户端连接的性能不足问题,官方推荐
Future 和 Promise
1.Future 用于获取异步操作的结果
2.ChannelFuture 有两种状态:uncompleted 和 completed
3. 异步 I / O 操作的超时
TCP 层面的 I / O 超时
业务逻辑层面的操作超时
4.Promise 是可写的 Future,Future 自身并没有写操作的接口
5.Netty 通过 Promise 对 Future 进行扩展,用于设置 I / O 操作的结果
6. 可能存在 I / O 和用户同时操作 Promise,设置结果时需要加锁保护,防止并发操作