netty 知识图谱
2021-02-21 21:49:10 1 举报
AI智能生成
netty java
作者其他创作
大纲/内容
Netty编码流程及demo
netty组件
Channel: 代表一个连接或者一个请求
ChannelHandler: 用于处理业务逻辑, 也有很多系统默认的handler
ChannelHandlerAdapter
ChannelInboundHandler
ChannelOutboundHandler
SimpleChannelInboundHandler
ChannelInitializer
ChannelHandlerContext: 作为channelpipeline的节点,
handler不适合直接作为节点, 需要context记录上下节点
handler不适合直接作为节点, 需要context记录上下节点
ChannelPipeline:责任链,每个channel都有自己的pipeline, 里面有各种handler
ByteBuffer
JVM ByteBuffer
Director ByteBuffer: 直接使用物理内存,避免GC
Codec: 本质上也是一种ChannelHandler
编码器Encode
解码器Decode
LineBasedFrameDecoder
以换行符为结束标志的编码器, 可以配置行的最大长度
以换行符为结束标志的编码器, 可以配置行的最大长度
StringDecoder:
把收到的消息对象转换为字符串的编码器
把收到的消息对象转换为字符串的编码器
DelimiterBasedFrameDecoder
FixedLemgthFrameDecoder
子主题
EventLoop
每个EventLoop都包含selector, thread
一个EventLoop, 可以处理多个channel,
一个channel只会被一个thread<EventLoop>处理,即线程安全
一个channel只会被一个thread<EventLoop>处理,即线程安全
EventLoop需要同时处理IO事件和非IO事件, 可以设置一个处理IO和非IO事件的时间占比.
IO事件: 读就绪时, 调用system call,将数据从内核空间拷贝至用户空间<阻塞>
非IO事件: 编码解码, 业务逻辑
IO事件: 读就绪时, 调用system call,将数据从内核空间拷贝至用户空间<阻塞>
非IO事件: 编码解码, 业务逻辑
不能将阻塞的业务逻辑放在EventLoop, 要用另外的线程处理
EventLoopGroup:
ServerBootstrap: 服务器端启动辅助类
Bootstrap: 客户端启动辅助类
ChannelInitializer:Channel初始化器
ChannelFuture: IO执行结果, 可以添加监听器执行操作
Netty实战
作为http服务器
作为websocket服务器
单一的TCP连接, 以双全工模式运行
HTTP是半全工模式运行
HTTP是半全工模式运行
无socket, 无header, 更高效
自定义协议
定义协议
编写编码解码handler
编写握手handler
编写认证handler
编写心跳handler
编写重连handler
编写业务handler
传统BIO
socket 的配置
缺点及优势
不利于高并发
并发数小于1000时性能较好
可以通过控制线程的方式限流
java demo
java NIO
组件
NIOServerSocketChannel
NIOScoketChannel
Selector
Buffer
SelectionKey
缺点及优势
编程过于复杂
使用了IO复用, 对于高并发有优势
jdk NIO 本身有bug
jdk NIO 需要自己处理网络闪断, 客户端重新连接等问题
java demo
读写就绪
读就绪: 只要内核空间有可读的内容select就会返回
写就绪: 只要内核空间有空闲 select就会返回 ;
一般写都是就绪的, 所以一般都不用注册写
一般写都是就绪的, 所以一般都不用注册写
如果有其他阻塞操作不应该在handler的线程中执行, 应当用另外的线程处理
IO核心概念
内核空间: 用户进程不能直接访问的内存,
只有操作系统内核可以访问
只有操作系统内核可以访问
用户空间: 用户进程可以使用的内存
DMA: 执行IO的硬件, 数据从磁盘到内核CPU不参与
零拷贝: 数据不通过内核空间, 直接拷贝到用户空间,
正常数据需要有DMA先拷贝到内核空间, 再由CPU拷贝至用户空间
正常数据需要有DMA先拷贝到内核空间, 再由CPU拷贝至用户空间
IO阻塞阶段
第一阶段: 由磁盘到内核空间的阻塞
第二阶段: 有内核空间到用户空间的阻塞
写数据同理
粘包拆包
由于TCP协议的问题<比如:缓存>客户端收到的数据不一定是一次一个完整的消息 .
定长协议
固定分隔符
边长协议: 类似于HTTP
序列化
JDK序列化
不能跨语言
性能低, 速度慢
序列化后字节流太大
thrift序列化
avro序列化
JSON序列化
把对象以json字符串的格式序列化成二进制
五种IO模式
阻塞IO: 再两个数据拷贝阶段都会阻塞
非阻塞IO: 不阻塞, 轮询, 占用CPU资源
IO复用: 使用了系统命令selector,poll,epoll
使用单个线程进行阻塞监听文件描述符状态, 当内核空间有数据可读/有空间可写时 返回,
这个selector线程需要以轮询的方式一直执行,
select读就绪时, 用户进程就会通过system call 将数据从内核拷贝到用户空间,
该过程是阻塞的
使用单个线程进行阻塞监听文件描述符状态, 当内核空间有数据可读/有空间可写时 返回,
这个selector线程需要以轮询的方式一直执行,
select读就绪时, 用户进程就会通过system call 将数据从内核拷贝到用户空间,
该过程是阻塞的
异步IO: 两个数据拷贝阶段都是非阻塞的,
DMA直接将数据拷贝到用户空间
DMA直接将数据拷贝到用户空间
信号驱动式IO
reactor网络编程模型
事件循环
reactor即基于事件驱动的模式, 通俗点就是回调的方式
JS就是单线程非阻塞, 如果有异步IO任务需要执行主线程并不会阻塞,
而是挂起该任务,等待任务结束后再执行对应的回调
而是挂起该任务,等待任务结束后再执行对应的回调
异步任务结束后会将回调函数加入到事件队列中, 等到主线程有空闲了才会执行队列中的回调函数
以netty为例, ChannelOutboundhandler会把回调函数放入事件队列,
当reactor发现写就绪后就会去回调队列里面执行函数
当reactor发现写就绪后就会去回调队列里面执行函数
IO复用结合线程池模式就是reactor的核心
Reactor
监听事件: 连接,写就绪,读就绪, 事件触发后,交由对用的handler处理
Handler
从channel读入数据, 处理业务逻辑, 从channel写出数据
单线程Reactor模型
redis使用的是单线程Reactor模型
但是如果并发量很高, 消息的编解码也是会很有压力的
单线程reactor与单线程BIO区别: 单线程BIO只能阻塞一个连接,
单线程reactor可以阻塞多个连接, 但是处理数据时是一样的
单线程reactor可以阻塞多个连接, 但是处理数据时是一样的
多线程Reactor模型
reactor线程池
reactor线程池中的每个线程都会有对应的selector, thread, handler
因为selector就绪后就会返回, 用户进程调用system call 将数据从内核拷贝到用户空间
改过程虽然是阻塞的,但是时间很短
改过程虽然是阻塞的,但是时间很短
如果是阻塞的操作, 就不应该有reactor线程池处理, 应该由另外的线程处理
acceptor线程
专门监听处理新建立的连接
也可以使用线程池,如果需要在建立连接时处理校验工作
主从模式
proactor模式
proactor模式使用的是异步非阻塞IO
netty5 使用的是proactor模式,
但是该版本已不再更新, 因为异步非阻塞支持不好
但是该版本已不再更新, 因为异步非阻塞支持不好
0 条评论
下一页