Netty学习

Netty是一个异步的、基于事件驱动的网络应用框架,用以快速开发高性能、高可靠性的网络IO程序;主要是针对在TCP写一下,面向Client端的高并发应用,或者是P2P场景下大量数据持续传输的应用;Netty本质是一个NIO框架,适用于服务器通讯的相关场景。

网络层次
Netty
NIO(io、网络)
原生的JDK io/网络
TCP/IP

应用场景
-RPC框架中作为基础通信组件。
-定制和开发私有协议栈。
-跨界点通信。

IO模型
BIO
同步并阻塞,服务器实现为一个连接一个线程,连接不做任何事情时会造成不必要的线程浪费。
NIO
同步非阻塞,服务器时限为一个线程处理多个连接,客户端连接在多路复用器上。
AIO
异步非阻塞,采用了Proactor模式,有效的请求蔡启动线程,现有操作系统完成后再通知服务端程序启动线程去处理。

三者适用场景比较:BIO适用于连接数目较少且固定的架构,NIO适用于连接数目多且连接比较短的架构,AIO适用于连接数目较多且连接比较长的架构。

BIO
NIO
三大核心部分:Channel通道、Buffer缓冲区、Selector选择器

1.Buffer缓冲区
本质上是一个可以读写数据的内存块,是一个容器对象,底层是一个数组。
具有四个属性:capacity表示容量,limit表示缓冲区的当前终点,position表示下一个读写的位置,mark表示标记

2.channel通道
类似于流,可以同时进行读写,异步读写数据,是一个接口。
3.Selector选择器
可以检测多个注册的通道上是否有事件发生。

零拷贝
零拷贝是网络编程的关键,常用的零拷贝有mmap内存映射和sendFile。
DMA:直接内存拷贝,不适用CPU
1.传统IO
传统IO总共发生四次上下文切换和四次拷贝,四次拷贝中含有两次DMA拷贝和两次cpu拷贝。

  • 用户进程通过read()方法向操作系统发起调用,此时上下文从用户态转向内核态
  • DMA控制器把数据从硬盘中拷贝到读缓冲区
  • CPU把读缓冲区数据拷贝到应用缓冲区,上下文从内核态转为用户态,read()返回
  • 用户进程通过write()方法发起调用,上下文从用户态转为内核态
  • CPU将应用缓冲区中数据拷贝到socket缓冲区
  • DMA控制器把数据从socket缓冲区拷贝到网卡,上下文从内核态切换回用户态,write()返回
    2.mmap优化
    mmap通过内存映射,将文件映射到内核缓冲区,同时,用户空间可以共享内核空间的数据,这样,就可以减少cpu拷贝次数。
    四次上下文切换和三次拷贝。
  • 用户进程通过mmap()方法向操作系统发起调用,上下文从用户态转向内核态
  • DMA控制器把数据从硬盘中拷贝到读缓冲区
  • 上下文从内核态转为用户态,mmap调用返回
  • 用户进程通过write()方法发起调用,上下文从用户态转为内核态
  • CPU将读缓冲区中数据拷贝到socket缓冲区
  • DMA控制器把数据从socket缓冲区拷贝到网卡,上下文从内核态切换回用户态,write()返回
    3.sendFile优化
    数据根本不经过用户态,直接从内核缓冲区进入到socketbuffer,由于和用户态完全无关,减少上下文切换次数。
    2次上下文切换和3次拷贝
  • 用户进程通过sendfile()方法向操作系统发起调用,上下文从用户态转向内核态
  • DMA控制器把数据从硬盘中拷贝到读缓冲区
  • CPU将读缓冲区中数据拷贝到socket缓冲区
  • DMA控制器把数据从socket缓冲区拷贝到网卡,上下文从内核态切换回用户态,sendfile调用返回
    4.sendfile+DMA Scatter/Gather优化
    便面了从内核缓冲区拷贝到socketbuffer的操作,直接拷贝到协议栈,从而再减少一次拷贝。
    2次用户态和内核态的上下文切换和2次拷贝。
  • 用户进程通过sendfile()方法向操作系统发起调用,上下文从用户态转向内核态
  • DMA控制器利用scatter把数据从硬盘中拷贝到读缓冲区离散存储
  • CPU把读缓冲区中的文件描述符和数据长度发送到socket缓冲区
  • DMA控制器根据文件描述符和数据长度,使用scatter/gather把数据从内核缓冲区拷贝到网卡
  • sendfile()调用返回,上下文从内核态切换回用户态

AIO
即NIO2.0,引入了异步通道的概念,采用了Proactor模式,简化程序编写。

原生NIO存在一些问题:类库和API复杂,需要具备额外技能,开发工作量大,jdKnio中包含bug,学习成本高,开发慢。

Netty入门
是一个异步基于事件驱动的网络框架。
1.线程模型
大致分为两种传统阻塞IO模型和Reactor模式。
Reactor又分为单Reactor单线程、单Reactor多线程和主从Reactor多线程。
Netty主要基于主从Reactor多线程模型做了一定的改进。
2.Netty模型

  • channe理解为数据通道。
  • msg理解为通道中流动的数据,经过pipeline的架构,可以编程其他对象,输出又变成ByteBuf
  • 把handle理解为数据的处理工序
    • 工序处理有多道,合在一起就是pipeline,pipeline负责发布事件(读、读完成)传播给每个hander,hander对自己感兴趣的事件进行处理。
    • hander分为inbound和outbound两类。
  • 把eventloop理解为处理数据的工人
    • 工人可以多个channel的io操作,一旦负责某个channel就要负责到底(绑定)。
    • 工人既可以执行io操作,也可以进行任务处理,每位工人有任务队列,队列里可以对方多个channel的待处理任务,任务分为普通任务和定时任务。
    • 工人按照pipeline顺序,一次按照handler的规划处理数据,可以为每道工序指定不同的工人。

3.组件
3.1Eventloop
事件循环对象
eventloop是一个单线程执行器,同时委会了一个selector,里面有run方法处理channel上源源不断的io事件。
事件循环组
eventloopgroup是一组eventloop,channel调用group的register方法来帮顶其中一个ecentloop,后续这个channel上的io事件都由此eventloop来处理。
3.2channel
主要作用close()、closeFuture()、pipeline()、write()和writeandflush()方法.
channelFuture
3.3future和promise
netty中的future继承自jdk的future,而promise有对netty future进行了扩展。
jdk future只能同步等待任务结束才能得到结果
netty future可以同步等待任务结束得到结果,也可以异步等待。
netty promise不仅有netty future的功能,而且脱离了任务独立存在,只作为两个线程间传递结果的容器。
3.4handle和Pipeline
channelhander用来处理channel上的各种任务,分为入站、出站两种。
head->h1->h2->tail,入站顺序和出战顺序相反
embeddedchannel可以用来测试。
3.4Bytebuf
对字节数据的封装,容量可以动态扩容,翻倍增加。
支持直接内存和堆内存,可以开启池化功能。
Bytebuf有四部分组成capacity、max capacity、读写指针。
针对不同的内存和池化机制,回收内存也不同,引用计数法回收

netty进阶
1.粘包和半包问题
只要是使用TCP协议,都会产生粘包半包问题。
TCP以一个段为单位,每发送一个段就需要进行一次确认应答,这样的缺点是往返时间长性能差,解决的方法是使用滑动窗口,窗口大小决定了无需等待应答而可以继续发送的数据最大值,起到了缓冲区的作用。
解决方法

  • 短链接,产生边界,能解决粘包问题。
  • 定长解码器,约定好发送的字节数。
  • 分隔符实现
  • LTC解码器,基于长度字段。
    2.协议的解析和设计
    2.1解析:以redis为例,set key value set 1 1就是*3$3set$11$11
    2.2自定义协议
  • 魔数 用来判断是否是无效数据包
  • 版本号 可以支持协议的升级
  • 序列化算法 序列化方式
  • 指令类型 登录注册等等类型
  • 请求序号 双工通信 一部能力
  • 正文长度
  • 消息正文
    @Sharable表示线程安全,handler只用创建一个实例。
    空闲状态检测器判断假死+心跳机制。

优化和源码
序列化算法优化,使用多种。
参数connect_timeout_millis客户端建立连接时,指定毫秒内无法连接会抛出异常,客户端用option配置参数,服务器端用childoption配置参数。
option是给serversocketchannel配置参数,childoption是给socketchannel配置参数。
so_backlog参数,半连接队列和连接队列的大小。
ulimit-n参数,fd最大数量。
tcp_nodelay参数,nagle算法的开启。
so_sndbug&so_rcvbuf参数,发送缓冲区和接收缓冲区。
allocator分配器,分配buf。
recbuf_allocator分配器,接受缓冲区大小。
参考:https://zhuanlan.zhihu.com/p/357820303#

posted @ 2022-06-06 18:28  壹号现充  阅读(122)  评论(0编辑  收藏  举报