48 网友分享了链接
2020-08-25 06:14:47
Netty 的接收和发送 ByteBuffer 采用 DIRECT BUFFERS,使用堆外直接内存进行 Socket 读 写,不需要进行字节缓冲区的二次拷贝。堆内存多了一次内存拷贝,JVM 会将堆内存 Buffer 拷贝一份到直接内存中,然后才写入 Socket 中。ByteBuffer 由 ChannelConfig 分配, 而 ChannelConfig 创建 ByteBufAllocator 默认使用 Direct Buffer CompositeByteBuf 类可以将多个 ByteBuf 合并为一个逻辑上的 ByteBuf, 避免了传统通过 内存拷贝的方式将几个小 Buffer 合并成一个大的 Buffer。addComponents 方法将 header 与 body 合并为一个逻辑上的 ByteBuf, 这两个 ByteBuf 在 CompositeByteBuf 内部都是单 独存在的, CompositeByteBuf 只是逻辑上是一个整体 通过 FileRegion 包装的 FileChannel.tranferTo 方法 实现文件传输, 可以直接将文件缓冲区 的数据发送到目标 Channel,避免了传统通过循环 write 方式导致的内存拷贝问题。 通过 wrap 方法, 我们可以将 byte[] 数组、ByteBuf、ByteBuffer 等包装成一个 Netty ByteBuf 对象, 进而避免了拷贝操作。 Selector BUG:若 Selector 的轮询结果为空,也没有 wakeup 或新消息处理,则发生空轮 询,CPU 使用率 100%, Netty 的解决办法:对 Selector 的 select 操作周期进行统计,每完成一次空的 select 操作进 行一次计数,若在某个周期内连续发生 N 次空轮询,则触发了 epoll 死循环 bug。重建 Selector,判断是否是其他线程发起的重建请求,若不是则将原 SocketChannel 从旧的 Selector 上去除注册,重新注册到新的 Selector 上,并将原来的 Selector 关闭。