初识Netty-前置知识

一、基本概念

          

1、IO的概念

  • input-读入数据:线程从某个源头读入数据放到缓冲区
  • output-输出数据:线程向某个目的地输出缓冲区内的数据

注:输入输出数据一般都需要操作系统支持,有些特殊情况不需要,如嵌入式(无操作系统)

2、 IO模型

     数据不会自主地从缓冲区进出到外部设备中,因此需要有线程等类似的驱动者去驱动数据的流动,即数据在线程驱动下,从缓冲区通过端口(如socket或其他)进出到外部设备,而IO的参照对象是缓冲区Buffer,进Buffer为读入,出Buffer为输出

  • 驱动者:驱动数据输入输出的线程或进程或控制流(cpu或类似的东西)
  • Buffer:缓冲区
  • socket:端口

       

3、IO的同步异步和阻塞非阻塞

(1)同步和异步

  标准:不同的动作是否按照固定的顺序执行,同步是按照固定顺序执行,俗称排队,异步反之

             IO概念中即是指,在IO请求返回和IO动作尝试之间是否有一个明确的顺序

  • 同步:IO请求返回的时候,IO尝试动作已经做完了,即返回的动作明确发生在IO尝试之后
  • 异步:请求返回只表明收到了请求,对实际的IO尝试不做任何保证,即在请求结果返回之前,IO动作可能其实已经做完了。如光纤传数据,有可能发送数据的指令刚做完,IO光纤就已经将数据发送完了,而cpu还正在执行return代码

       异步举例:Linux的AIO是纯异步的,其他IO基本都是同步的

       可参见:linux AIO_aio linux_西门吹大雪的博客-CSDN博客 

(2)IO阻塞和非阻塞 

     一般在同步下才有意义

  • 阻塞:彻底完成IO动作,或达到某个条件(如超时),或发生错误之后才返回请求
  • 非阻塞:尝了IO的动作后就返回请求,不保证全部IO动作都完成之后才返回

(3)组合

  • 同步+阻塞:IO动作既是按照顺序执行的又保证每个IO动作有个终结性结果才返回请求(一般)
  • 同步+非阻塞:动作按顺序执行,但不保证每个IO动作有个终结性结果才返回请求(多线程)
  • 异步+阻塞:动作不按顺序执行,但每个IO动作有个终结性结果才返回请求
  • 异步+非阻塞:动作既不按照顺序执行,也不保证每个IO动作有个终结性结果才返回请求

二、各层的IO

       

  

(一)操作系统OS中IO(POSIX接口为例)

                    

1、特点

  • 操作系统提供了封装好的IO操作接口,屏蔽了IO动作细节
  • 接口为文件形式操作接口:open、close、read、write、ioctl(一切皆文件)
  • 应用线程或进程自己去确定调用IO接口的时机(驱动方为线程或进程)
  • 提供稳定的同步(阻塞或非阻塞)IO接口(默认阻塞)和异步接口(AIO)

 2、同步阻塞IO接口

(1)特点

  • 阻塞模式下,一个线程处理一个对象
  • 响应最快,cpu资源最省

 (2)问题

     需要处理的IO对象多了,就需要很多的线程,随之而来多线程的问题:

  • 线程内存消耗(每个线程都需要对应的内存)
  •  线程调度操作变多
  • 线程/进程切换会导致Cache line,进程内存映射的TLB块表失效等问题,需要大量的cpu来处理线程切换

                             

(3)解决多线程带来的资源损耗问题--减少线程数

  • IO对象设置为同步非阻塞模式,提供专门的轮询线程去管理所有需要做IO的端口并交给对应的业务线程去做
  • 问题:IO操作是没有时表不确定的,因此大量cpu浪费在轮询上,如果设置轮询线程的sleep时间,又会增加响应时间

                                

 (4)解决轮询线程空转问题---通知机制select

  • 由于IO的状态变化是通过OS的动作来的,因此通过OS内核的支持将轮询改为通知
  • 这样的通知机制抽象为一个IO状态通知器(同步阻塞/非阻塞形式的接口)
  • 特点:

<1>通知器本身不做任何IO操作,只负责状态变更通知管理

<2>接口的形式与OS强相关

           

                               

  注:上述方法讲述的是如何用更少的线程 解决更多的IO,另一种方式是通过减少资源消耗大方面,让线程变得轻量级,从内核级别到用户级别:

用户级线程, Windows Fiber ,协程,用户级通知库 libevent
Java 中Project Loom, go中 Goroutine , Erlang
内核 / 内核
软件固件化(电路的并行化特点)

(二)JAVA中IO

1、JVM层

  • JAVA基于虚拟机,屏蔽系统差异性,操作系统解决的问题在虚拟机层面上要重新解决一次(JAVA的接口形式提供)
  • 一个java的线程对应一个OS的线程
  • IO(OIO) ----线程太多开销大----轮询线程CPU浪费----提供IO通知器的新IO(NIO)

2、OIO和NIO的类

(1)OIO(包括同步阻塞BIO和同步非阻塞)

java.net.ServerSocket

java.net.Socket

java.net.DatagramSocket

(2)NIO

java.nio.Buffer

java.nio.channels.Channel

java.nio.channels.Selector

3、两个IO对比

(1)OIO

     OIO中的Socket基于OS的同步IO接口完成IO动作,提供的是流式的接口,不是基于buffer

(2)NIO

各种 Channel 基于 OS 的同步 IO 接口做 IO 动作
Java 又基于 OS 提供的通知机制,面向用户提供纯 Java 语言统一的 IO 通知接口 Selector
在不同的 OS 上依赖的接口是不一样的

           

3、详解NIO

(1)NIO的使用

SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("localhost", 80));
//默认是同步阻塞的,设置成非阻塞模式,防止selector阻塞在channel中
channel.configureBlocking(false);

Selector selector = Selector.open();
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);

while(true) {
	int readyChannels = selector.selectNow();
	if(readyChannels == 0) continue;
	Set<SelectionKey> selectedKeys = selector.selectedKeys();
	Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
	while(keyIterator.hasNext()) {
	  SelectionKey key = keyIterator.next();
	  if(key.isReadable()) {
	      // a channel is ready for reading
	      ..... //Dispatch to process reading
	  } 
	  keyIterator.remove();
    } 
  }
}

(2)流程图

                

 (3)组成

  • Buffer---最基础的实现为ByteBuffer,可以理解为扩展了功能的byte数组(byte[]),支持字节转换成其他基本类型 

                                       

        注:directBuffer较heapBuffer少一次copy,为保证数据一致性,对于堆内的数据受GC影响,因此使用堆数据之前先将堆内的数据copy到用户区,然后再进行后续操作

 

  • selector---java层面实现的IO通知器 

<1>定义了4种可以侦听和通知的事件,当通知某个Channel发生了事件时,准确的含义是“这个Channel准备好了做这个事件”:Accept, Connect, Read, Write 

<2>当Channel被注册到Selector上时,会获得一个SelectionKey,作为存根,以便后续的操作

InterestSet , 感兴趣,也就是期望侦听的事件
ReadySet ,准备好了的事件
Selector Channel AttachedObject ( 即用户自定义数据 )

 <3>选择(侦听)动作(方法)

int select()
i nt select(long timeout )
i nt selectNow ()

<4>唤醒等待中的Selector

有期望的事件发生
其他线程调用 wakeUp () 或者 close()
有异常发生

(三)Nettyt中IO

   三层IO的调用关系:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值