Netty学习笔记

一、IO模型

1.介绍:

UNIX网络编程对IO模型提供5种模型分类,基本分为两个阶段:

第一阶段内核数据准备好、第二阶段进程从内核拷贝数据

根据第一阶段数据是否准备好进程的状态分为:

​ ** 1.阻塞IO:**内核数据未准备好则一直阻塞等待至数据准备好

​ ** 2.非阻塞IO:**内核数据未准备好则直接返回一个错误信号接着一般采用轮询,待成功后拷贝数据

​ ** 3.IO复用:!!!!**linuix提供select/poll,进程可以利用select检测多fd状态,但是select/poll是顺序扫描且支持fd数量有限1024,linux还提供epoll,epoll是事务驱动型,性能更高。简单来说就是多线程处理多请求

根据第二阶段进程从内核拷贝数据状态分为:

​ ** 4.信号驱动IO:**进程查询内核数据是否准备好,此系统调用立即返回,可非阻塞以执行其他操作,数据就绪时为该进程生成sigio信号,此时进程来读取数据

​ * *5.异步IO:**就是由内核完成整个操作,通知我们时操作已经完成了

2.分析:

1.BIO:典型的1:1,来一个创建一个,资源消耗太大

2.伪异步IO:利用线程池或者消息队列实现的IO,本质上仍是同步阻塞IO,一定程度上降低资源的恶性开销

3.NIO:非阻塞IO

4.AIO:异步非阻塞IO

5.对比:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8qCLh2R1-1596092680094)(/Users/leo/Library/Application Support/typora-user-images/image-20200715141128886.png)]

二、Netty开发指南

1.概述:

Java NIO的核心就是多路复用IO技术,而堵路复用核心就是Selector轮询注册阿在其上的Channel,当发现某个Channel处于就绪态,从阻塞状态返回就绪的Channel的选择键集合进行I操作

直接使用java Api太复杂,而且还有epoll bug,导致selector空轮询,cpu100%

2.NIO组成

属性说明
capacity容纳最大容量,创建默认
limit第一个不能操作的元素或缓冲区现存计数
position下一个要被操作的索引,位置由get/put操作
mark一个备忘位置,调用mark()方法来设定,mark=position,调用reset方法设定position=mark。标记在设定前是未定义的(undefined)
mark <= position <= limit <= capacity
一些操作
方法名作用
put写,limit原位置不动,position移动
flip读写切换,limit=position,position=0
get读,position++,limit不动
clear清空,当时数据并没被删除,只是几个位置被置初始位置从头开始了
hassRemaining检查position与limit之间否还有元素
rewind重读元素,position=0,注意与flip区别

Netty过程

Netty利用Reactor模型,内部实现两个i线程池,默认起cpu*2个线程,在bind之后完成,一个boss,一个work,boos线程池粗则处理请求accept事件,接收到请求时将对应的socket封装到NioSocketChannel,交给work线程池由它来处理请求事件并由对应的handler处理

netty零拷贝

1.采用直接内存,免去了原先堆将内存拷贝一份到直接内存再写入socket中
2.提供组合buffer对象,避免原先将多个小buffer合并成一个buffer的操作
3.netty直接将数据发送到目标channel,避免传统通多循环写方式导致的内存拷贝问题

重要组件

名称作用
channel核心抽象类,基本上所有操作都是发生在其上
channelFuture因为是异步的IO操作,以此来来注册监听事件,自动返回操作的的结果
channelHandler处理出入操作的逻辑,可以构成责任链,可以依次处理各种事C件
channelPipeline为handler提供容器,并产生一个channelHandlerContext对象用来管理二者之间的关系

发送消息的方式

1.直接写入channel,在channelPepline中依次移动,遇到不合适就跳过
2.要是想跳过某些handler或者有目标的handler,可以将消息写入目标handler对应的上一个handler绑定的channelHandlerContext中,然后依次向下移动

netty心跳机制

目的:检测连接情况
实现:
1.TCP协议层的keepAlive
不是标准协议,默认关闭,依赖于操作系统不够灵活,换成udp协议失效
2.应用层自定义实现心跳机制
netty中实现心跳机制主要时IdleSateHandler,可以堆一个channel的读写设置定时器,当一段时间内没有数据交互就会出发指定事件
参数:1
readerIdleTime:读超时
writteIdleTiime:写超时
allIdleTime:读写超时

Netty工作架构图

异步非阻塞模式 Reactor详解

###1.单线程
所有IO操作都有一个线程完成,多路复用,事件的分发预处理都在一个reactor线程上完成,性能差,不适合高并发、高负载的场景
###2.多线程
监听操作单独再一个NIO线程Acceptor上负责接收客户端的TCP链接,其他剩下的NIO线程池中的线程负责网络的IO操作。百万量级的链接或认证时,一个Acceptor有些捉襟见肘
1

   1.Reactor 对象通过select监控客户端请求事件,收到事件后,通过dispatch进行分发
   2.如果是连接请求,则右Acceptor通过accept处理连接请求,然后创建一个Handler对象处理完成连接后的各种事件
   3.如果不是连接请求,则由Reactor分发调用连接对应的handler来处理
   4.handler只负责相应事件,不做具体的业务处理,通过rad读取数据后,会分发给后面的worker线程池的某个线程处理业务
   5 worker线程池会分配一个独立的线程,完成真正的业务,同时把处理的结果返回给handler
   6 handler收到响应后,通过send将结果返回给client
   优点:
   可以充分利用多核CPU的处理能力
   缺点:
   多线程会数据共享和访问比较复杂,reactor处理了所有的事件的监听和相应,在单线程运行,在高并发场景容易出现性能瓶颈

3.主从多线程

将原reactor拆分成main与sub两部分,main负责接入认证、握手等操作,Acceptor负责监听端口、接收客户端连接、sub则负责事件分发处理等

    1.Reactor主线程MainReactor对象通过select监听连接事件,收到事件后,通过Acceptor处理连接事件
    2.当Acceptor处理连接事件后,MainReactor将连接分配给SubReactor
    3.subReactor将连接加入到连接队列进行监听,并创建handler进行各种事件处理
    4.当有新的事件发生时,subReactor就会调用对应的handler进行处理
    5.handler通过rand读取数据,会分发给后面的worker线程进行处理
    6.wroker线程池会分独立的worker线程进行业务处理,并返回结果
    7.handler收到响应的结果后,再通过sned将结果返回给client
    8.Reactor主线程可以对应多个Reactor子线程,即MainReactor可以关联多个subReactor。
    优点:
    父线程与子线程的数据交互简单,职责明确,父线程只需要接收新连接,子线程完成后续的业务处理
    父线程与子线程的数据交互简单,Reactor主线程只需要把新连接传给子线程,子线程无需返回数据
    缺点:
    编程复制读较高。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值