netty入门

简单Server和简单Client

1

几大组件的关系

channel,eventLoopGroup,ByteBuf,Handler,pipline

EventLoop

事件循环对象,本质就是单线程执行器

事件循环组(EventLoopGroup),channel一般会调用EventLoopGroup中的register来绑定其中一个channel,后面channel上的io事件都由此EventloopGroup来负责,也保证了io处理时的线程安全

NioEventLoop 底层基于NIO

DefaultEventLoop

Channel

作用

- <font style="color:rgb(31, 35, 40);">close() 可以用来关闭 channel</font>
- <font style="color:rgb(31, 35, 40);">closeFuture() 用来处理 channel 的关闭</font>
    * <font style="color:rgb(31, 35, 40);">sync 方法作用是同步等待 channel 关闭</font>
    * <font style="color:rgb(31, 35, 40);">而 addListener 方法是异步等待 channel 关闭</font>
- <font style="color:rgb(31, 35, 40);">pipeline() 方法添加处理器</font>
- <font style="color:rgb(31, 35, 40);">write() 方法将数据写入</font>
- <font style="color:rgb(31, 35, 40);">writeAndFlush() 方法将数据写入并刷出</font>

注意 connect,bind 方法是异步的,意味着不等连接建立,方法执行就返回了。因此

channelFuture 对象中不能【立刻】获得到正确的 Channel 对象

两种方法:线程sync()阻塞等待建立好,addListener() 添加回调方法

Future & Promise

Handler & Pipeline

多个Handler组成一个pipeline

ByteBuf

是对字节数据的封装

创建

1
2
3
4
5
6
7
ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(10);//默认使用 池化基于直接内存的 ByteBuf
log(buffer);
ByteBuf buffer = ByteBufAllocator.DEFAULT.directBuffer(10);

//基于堆
ByteBuf buffer = ByteBufAllocator.DEFAULT.heapBuffer(10);

堆内存和直接内存

堆内存:多一次拷贝,需要从os 本地内存拷贝到Java的堆内存

磁盘-》os

os-》Java heap内存

数据需要 两次拷贝,效率较低

直接内存:零拷贝技术,只需要一次拷贝

池化 vs 非池化

池化的最大意义在于可以重用 ByteBuf,优点有

  • 没有池化,则每次都得创建新的 ByteBuf 实例,这个操作对直接内存代价昂贵,就算是堆内存,也会增加 GC 压力
  • 有了池化,则可以重用池中 ByteBuf 实例,并且采用了与 jemalloc 类似的内存分配算法提升分配效率
  • 高并发时,池化功能更节约内存,减少内存溢出的可能

组成

write

writeByte,writeInt….

扩容规则

未超过512,下一个则是超过它的第一个16的整数倍

如果超过521,下一个则是超过它的第一个2的n次方数

read

readByte()

markReaderIndex() 标志

resetReaderIndex() 重置

retain & release