Netty

  • Java 的AIO
    重要的三个类:AsynchronousServerSocketChannel(服务端)、AsynchronousSocketChannel(客户端)和CompletionHandler(用户处理器);
    CompletionHandler接口实现应用程序向操作系统发起IO操作

  • 五种IO通信模型
    1)阻塞IO
    2)非阻塞IO
    3) 多路复用IO(selector 复用器)重点
    本质和阻塞IO类似,相较于阻塞IO更适合用于处理多连接高并发的情形,常见于:Java NIO、Nginx;
    4)信号驱动IO
    伪异步
    5)异步IO
    适合用于高性能高并发应用

  • 同步和异步
    同步和异步是指CPU时间片的利用,主要看请求发起方对结果的获取是主动还是被动的;
    发起结果获取请求后,
    ​同步阻塞:一直等待应答
    同步非阻塞:可以先处理其他事情,但要不断轮询结果
    异步阻塞:等待系统通知结果,但是同时自己也一直在等通知
    ​异步非阻塞:处理其他事情,系统处理完成后通知自己

  • NIO&BIO
    NIO其实也是阻塞的:只不过他阻塞的时间段只在于数据从内核态到用户态的拷贝过程,是面向缓存区来设计的
    BIO是面向流的,NIO是面向缓冲区的;
    面向流:数据在一个流上,直来直去的,中间不间断顺序也不能乱,从头到尾都必须一直等待;
    面向缓冲区:数据将被装到一个缓冲区里,就像先翻一个桶在哪里,当水龙头里面的水来了之后,就会自动装到这个桶里,这里就有些复 杂的情况了:
    1.当水太少,装不满桶,不够用;
    2.对自己需要的水量预估不足或者额外多了一些水进来,最后我们都不能得到我们想要的结果,最终我们只能不都拿的去检查水桶里的水是否足够,这其实花费了更多的开销。
    Java 1.7 的NIO才真正实现了异步IO,即AIO。

  • Mina & Netty
    都是韩国大神Trustin Lee的作品
    对比:两者有很多特性都一样
    Mina依赖于Apache
    Netty依赖于JBoss
    一般使用中两者性能相差无几

  • 概念
    Netty三大核心组件:缓冲区Buffer、选择器Selector、通道Channel

  • Buffer
    Buffer的基本用法就是:
    初始化(allocate)–> 写入数据(read / put)–> 转换为写出模式(flip)–> 写出数据(get)–> 转换为写入模式(compact)–> 写入数据(read / put)…
    position:指定下一个将要读取或者写入的位置,初始值为0,由put()或get()自动维护
    limit:指定还有多少数据需要读取或者还有多少空间能够被写入
    capacity:缓冲区的容量,即底层数组的大小;
    flip():重设缓冲区,将当前位置设为限制值,然后将当前位置设为0;
    hasRemaining():查看当前位置和限制值之间是否有元素;
    remaining():返回剩余元素个数;
    alloctate():初始化一个指定大小的缓冲区;
    wrap():将现有数组包装为缓冲区;
    slice():分片,截取缓冲区的一个窗口,方便操作,大小为从postion到limit;
    asReadOnlyBuffer():只读缓冲区;
    allocateDirect():直接缓冲区,尽量避免中间copy操作,使得IO速度更快;
    mappedByteBuffer:内存映射

  • Selector
    selector是注册各种IO事件的地方,当这些事件发生之后,它就会告知我们发生的所有事件;
    每个事件有对应的selectionKey ;
    selectionKey 对应了事件发生的通道(Channel);
    通过selectionKey 拿到Channel我们就可以进行数据读写等操作;
    NIO编程基本就是分三步:
    1)向Slector注册感兴趣的事件;
    2)从Selector中读取感兴趣的事件;
    3)处理事件

  • Channel
    它是一个对象,通过它可以读取或者写入数据;当然所有数据都是通过Buffer对象来处理,我们永远不会将字节直接写进Channel,而是先写进缓冲区,读取也是同理;
    使用NIO读取分为三步:
    1)从Stream中获取Channel;
    2)创建Buffer;
    3)将数据从Channel读取到Buffer;
    类似的,写入也是三步:
    1)从Stream中获取Channel;
    2)创建Buffer;
    3)将数据从Buffer写入到Channel;

  • 其他
    文件描述:即FileDescriptor,与底层IO相对应,IO通过这个来操作文件,获得文件描述:IOUtil.makePipe()
    pipeLine: 是Netty的职责链,用来存放各种handler;
    context: 用于封装hander,方便操作;
    handler: 每个hander都在单独线程执行;
    handler主要分为inbound(入站)和outbound(出站),执行顺序遵循:inbound先add的先执行,而outbound先add后执行。

  • 多路复用
    主要包括四种:select、poll、epoll、kqueue
    对于java而言,windows下仅支持select一种,这种技术特别适合高并发场景(1ms上千请求);其他场景这一设计模式并不能发挥优势;

  • Netty和NIO
    Netty采用NIO而非AIO的理由:
    1)Netty不看重windows上的使用,在Linux上,AIO底层仍使用epoll,没有很好的实现AIO, 性能上么有明显优势;
    2)Netty采用Reactor模型,而AIO采用Proactor;
    3)AIO有个缺点就是:接收数据需要预先分配缓存,而NIO是需要接收时才分配缓存,因此对于对连接数量非常大但流量小的情况,AIO浪费了很多内存;

  • Bootstrap
    Bootstrap是一个用来初始化Netty的工厂类;

  1. handler()和childHandler()的主要区别是,handler()是发生在初始化的时候,childHandler()是发生在客户端连接之后

    也就是说,如果需要在客户端连接前的请求进行handler处理,则需要配置handler(),如果是处理客户端连接之后的handler,则需要配置在childHandler()。

  2. 对于ChannelOption.SO_BACKLOG的解释

服务器端TCP内核模块维护有2个队列,我们称之为A,B吧
客户端向服务端connect的时候,发送带有SYN标志的包(第一次握手)
服务端收到客户端发来的SYN时,向客户端发送SYN ACK 确认(第二次握手)
此时TCP内核模块把客户端连接加入到A队列中,然后服务器收到客户端发来的ACK时(第三次握手)
TCP没和模块把客户端连接从A队列移到B队列,连接完成,应用程序的accept会返回
也就是说accept从B队列中取出完成三次握手的连接
 
A队列和B队列的长度之和是backlog,当A,B队列的长之和大于backlog时,新连接将会被TCP内核拒绝
所以,如果backlog过小,可能会出现accept速度跟不上,A.B 队列满了,导致新客户端无法连接,
要注意的是,backlog对程序支持的连接数并无影响,backlog影响的只是还没有被accept 取出的连接
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值