Netty的编码与解码

  1. 编解码:出站消息会把Java对象转换成字节,入站消息则将字节转成Java对象
  2. Netty内部提供了一系列内置编解码API
  3. 如StringEncoder和StringDecoder和编解码对象的ObjectEncoder和ObjectDecoder
  4. 如果要实现高效的编解码可以用protobuf
  5. protobuf要维护大量proto文件,比较麻烦,一般可以使用protostuff,使用简单

Netty粘包拆包

  • TCP是一个流协议,就是没有界限的一长串二进制数据
  • TCP作为传输层协议并不不了解上层业务数据的具体含义
  • 务上认为是一个完整的包,可能会被TCP拆分成多个包进行发送
  • 也有可能把多个小的包封装成一个大的数据包发送
  • 以上描述的就是粘包和拆包,如何解决?
    • 消息定长,不够补空位;有点浪费
    • 消息数据包尾部添加特殊结束符;简单,但要保证内容不能出现特殊符号
    • 发送数据时,将数据长度一并发送出去;
  • Netty内置有3种编码器支持分包操作
    • LineBasedFrameDecoder(回车换行分包)
    • DelimiterBasedFrameDecoder(特殊分隔符分包)
    • FixedLengthFrameDecoder(固定长度报文来分包)
    • 也可自定义

Netty心跳检测机制

  1. 客户端和服务器之间定期发送的一种特殊的数据包,通知对方自己还在线
  2. Netty中实现心跳机制的关键是 IdleStateHandler

断线重连

  1. 网络出现问题,客户端需要支持重连机制
  2. 客户端断开连接后可感知到,并通过Handler的channelInactive方法进行重连

Netty高并发高性能架构设计精髓

  1. 主从Reactor线程模型

  2. NIO多路复用非阻塞

  3. 无锁串行化思想

    • 消息的处理尽可能在同一个线程内完成
    • 避免了多线程操作导致的锁的竞争
    • NIO的多路复用就是一种无锁串行化的设计思想
  4. 高性能的序列化协议

  5. 零拷贝,使用直接内存

    • 直接内存并不是虚拟机运行时数据区的一部分
    • 也不是Java虚拟机规范中定义的内存区域
    • java里用DirectByteBuffer可以分配一块直接内存(堆外内存)
    • 元空间对应的内存也叫作直接内存,它们对应的都是机器的物理内存
    • 直接内存申请较慢,但访问效率高
    • 零拷贝:直接内存=>系统调用=>硬盘/网卡
    • 二次拷贝:堆内存=>直接内存=>系统调用=>硬盘/网卡
    • 优点:不占用堆内存空间,减少了发生GC的可能,访问效率高
    • 缺点:初始分配慢,没有JVM直接管理内存,容易发生内存溢出
    • 通过-XX:MaxDirectMemorySize来指定阈值,达到阈值后会触发FULLGC回收内存
    • 零拷贝:使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝 Netty高级特性及源码详解-LMLPHP
  6. ByteBuf内存池设计

    • Netty提供了基于ByteBuf内存池的缓冲区重用机制
    • 需要的时候直接从池子里获取ByteBuf使用即可
    • 使用完毕之后就重新放回到池子里去
  7. 灵活的TCP参数配置能力

    • 根据实例业务情况,合理设置TCP参数,可有效提升性能
    • 比如设置:发送缓冲区和接收缓冲区
06-18 20:16