(NIO编程)Netty框架学习

java的三种IO

  1. BIO(传统的阻塞型):每次连接都会开一个线程,但是这个连接不做任何事情的话会造成不必要的线程开销。jdk1.4之前唯一的选择。加入线程池机制改善(多个客户端连接服务器)。
  2. NIO(同步非阻塞):一个线程处理多个请求,轮询到连接有IO请求上去处理,节省线程开销。适用于连接数目多且连接比较短。jdk1.4开始支持。
  3. AIO(异步非阻塞)。连接数目多且连接比较长。

NIO原理

一个线程维护一个Selector,一个Selector下面又维护多个通道,通道与每个客户端之间有一个缓存Buffer(底层是一个数组),Buffer既可以读也可以写(flip方法切换),通道是双向的。

  1. put放入的需和get取出时采用的类型一致,否则报BufferUnderflowException错误。
  2. 只读的buffer,写入时报ReadOnlyBufferException异常。
  3. MappedByteBuffer(实际类型是DirectByteBuffer)修改后的须在外部打开,不能直接看Idea里面的,idea里的他还没更新。
MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_WRITE, 0, 5);
	参数1 FileChannel.MapMode.READ_WRITE 使用的读写模式
	参数2 0:可直接修改的起始位置
	参数3 5:映射到内存的大小(1.txt的多少个字节映射到内存)
	可以直接修改的范围就是0-5(不是下标为5而是最多5个字节)
  1. 大致步骤。
    在这里插入图片描述
  2. SelectionKey(表示Selecor和网络通道的注册关系共四种)

零拷贝

  1. 零拷贝是指从操作系统角度看没有Cpu拷贝。
  2. DMA:直接拷贝内存(不使用CPU)windows系统一次最多发8m大小的字节,超过8m需分次数发送。
        SocketChannel socketChannel=SocketChannel.open();//获取socket通道
        socketChannel.connect(new InetSocketAddress("127.0.0.1",10086));//绑定服务器
        FileChannel channel = new FileInputStream("1.exe").getChannel();//获取文件输出通道
        long start=System.currentTimeMillis();
        long fileLength=channel.size();//获取文件大小
        int m8=1024*1024*8;//每次最多发送的字节数
        long count=fileLength/m8+1;//发送次数 +1 是为了例如 8m+1字节的文件,当除了之后为1,需要把剩下的字节也输出
        int index=0;//每次的定位
        for (int i=0;i<count-1;i++){
            index += channel.transferTo(index,m8,socketChannel);//发送给对方的socket通道
        }
        if (fileLength-index!=0){//当有剩余的就把剩余的发送了
            index += channel.transferTo(index,fileLength-index,socketChannel);
        }
        System.out.println((System.currentTimeMillis()-start)+"ms");
        System.out.println("总字节数"+index);
  1. 单Reactor单线程(在处理读写业务时阻塞,会导致性能瓶颈)。
  2. 单Reactor多线程 (可以充分利用多核cup的处理能力,多线程数据共享和访问比较复杂,rea ctor处理所有事件的监听和响应,在单线程运行,在高并发场景容易出现性能瓶颈)。
  3. 主从Reactor多线程(父线程和子线程分工明确,父线程只需要接收新连接,子线程完成后续的业务处理,父子线程的数据交互简单,Reactor主线程只需把新连接传给子线程,子线程无需返回数据)。

Netty模型

B站尚硅谷

  1. NioEventLoopGroup对象的两个Group没有指定线程数的话默认为cpu核数乘以2,由源码Math.max(1, SystemPropertyUtil.getInt("io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2))可知。
  2. ctx包含了pipeline和channel而pipeline和channel互相包含。
  3. 防止耗时任务阻塞可以采用异步队列方式(TaskQueue),或者定时任务队列方式(ScheduleTaskQueue)以及
  4. Future说明 表示异步的执行结果,可以通过他提供的方法来检测执行是否完成;ChannelFuture是一个接口(public interface ChannelFuture extends Future<Void>),可添加监听器,当监听的事件发生时,再去处理相应的逻辑,不用阻塞的等待这个事件处理完,更加的稳定。
  5. ChannelHandlerContext保存Channel相关的所有上下文信息,同时关联一个ChannelHandler对象;即包含了一个具体的事件处理器同时也绑定了对应的pipeline和channel。
  6. ChannelOption.SO_BACKLOG参数等同于TCP/IP协议中的backlog参数,初始化服务器可连接队列大小,指定了队列的大小。
  7. ChannelOption.SO_KEEPALIVE一直保持连接活动状态。
  8. Unpooled类,获取的Buffer会自动扩容,
  9. Netty心跳机制
  10. netty序列化效率差,无法跨语言(底层采用的是java序列化)。

Protobuf

  1. 用来序列化,可以多语言互用。

Encoder和Decoder

  1. 进行编/解码时,注意处理的数据类型和发送的数据类型是否一致,如果不一致将不会进行编/解码。
  2. 压缩编解码器。
  3. 分隔符编解码器。
  4. 指定长度编解码器

源码

  1. 将传进来的类通过channelFactory反射创建channel。
  2. addLast添加双向链表。
  3. doMessage方法通过ServerSocket的accept方法获取到Tcp连接,然后封装成neety的NioSocketChannel对象
  4. 心跳 IdleStateEvent event = IdleStateHandler.this.newIdleStateEvent(IdleState.ALL_IDLE, first);
    IdleStateHandler.this.channelIdle(ctx, event);
    这样将时间传递过去。
  5. 异步提交的两种方式:
    1、static final EventExecutorGroup group=new DefaultEventExecutorGroup(16);//线程池处理业务 private final Mytask mytask=new Mytask();//具体实现业务的类 @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("NettyServerHandler__"+Thread.currentThread().getName()); //将任务提交到线程池 mytask.setParam((ByteBuf)msg,ctx); group.submit(mytask);
    2、在initChannel中添加 channel.pipeline().addLast(new DefaultEventExecutorGroup(2),new NettyServerHandler());//任务直接交给前面那个线程池处理。new DefaultEventExecutorGroup(2)可以用一个静态变量取代,这样写了之后业务就会直接用这里面的线程处理,没加的话就是默认的。
    第一种好些,因为可以自己决定用不用提交任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

syf_wfl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值