《Netty 实战》第4,5,6章

传送门
《Netty 实战》第1,2,3章
《Netty 实战》第4,5,6章
《Netty 实战》第7,8,9章
《Netty 实战》第10,11章
《Netty 实战》第12,13章

第4章 Netty-传输

  1. 传输迁移
    原始Jdk API(阻塞与非阻塞不统一),NIO接口复杂,而Netty抽象了统一的接口,对OIO和NIO一视同仁.从demo可见仅EventLoopGroup与ServerSocketChannel类型不同.

  2. 传输API-channel

    《Netty 实战》第4,5,6章_第1张图片
    channel-interfaces.png

    a. channel 关联pipeline和channelConfig
    b. pipeline,一直过滤器模式(Intercepting Filter)
    c. Channel方法

    《Netty 实战》第4,5,6章_第2张图片
    channel-methods.png

  3. 内置的传输模型


    《Netty 实战》第4,5,6章_第3张图片
    netty-trans.png

    a. NIO: 默认用的,提供了一个所以I/O操作的全异步实现(netty强大之处),复杂的异步操作由netty实现了,对用户隐藏.
    b. Epoll: 仅linux系统可用的高效nio.

    《Netty 实战》第4,5,6章_第4张图片
    status-changes.png

    c. Oio: 实际上,netty用异步模拟同步,保证了接口的一致
    d. Local: 用于JVM内部通讯(无demo)
    e. Embedded: 用于测试Handler(第9章)

  4. 传输的用例: 应用程序需求与推荐传输方式

    《Netty 实战》第4,5,6章_第5张图片
    selected.png

第5章 Bytebuf-Netty数据容器

  1. API(ByteBuf和ByteBufHolder)
    优点:类型扩展,零拷贝,容量增长,无需flip,不同索引,链式调用,引用计数器,池化.

  2. ByteBuf类
    a.工作原理: 维护两个不同索引(readIndex和WriteIndex),用一个Capacity控制容量的增长.
    b. 使用模式: 堆缓冲区(heap),直接缓冲区(derected)-避免内存整理的JVM资源浪费,复合缓冲区(Composite)

  3. 字节级操作:


    《Netty 实战》第4,5,6章_第6张图片
    ByteBuf.png

    a. 随机访问: 传入索引即可=> getByte(i)
    b. 顺序访问: ?与上面一样啊.
    c. 可丢弃字节( 介于原标签到ReaderIndex之间),可被整理=>discardReadBytes
    d. 可读字节(介于ReaderIndex和WriteIndex之间),readableBytes
    e. 可写字节(介于WriteIndex和Capacity之间),writeableBYtes
    f. 索引管理: mark,reset => clear()仅移动所有,不改内存,比discardReadBytes高效,也更不安全.
    g. 查找操作: forEachByte(传入ByteProcessor)
    h. 派生缓冲区: slice(),相当于一个内存有两套Index,高效(不需重新分配),冲突(无法感知另外一套读写),一般来说生成只读的派生缓冲区还是比较安全的
    i. 读写操作(get/set,read/write)
    j. 其他

  4. ByteBufHolder接口, content(),copy(),duplicate()

  5. ByteBuf分配
    a. ByteBufAllocator接口,与使用模式有关(Pooled和Unpooled)
    b. Unpooled缓冲方法
    c. ByteBufUtil工具类(静态方法调用)

  6. 引用计数ReferenceCounted
    由于ByteBuf可能在堆外,因而Netty需要自行管理缓冲区,使用ReferenceCounted对活动对象的引用进行计数,当被引用的数量为0时,释放内存空间

第6章 ChannelHandler和ChannelPipeLine(重点章节)

channel负责网络连接,ByteBuf负责管理传输的内容,Handler负责处理业务逻辑.

  1. ChannelHandler家族
    a. 生命周期


    《Netty 实战》第4,5,6章_第7张图片
    channel-life.png

    《Netty 实战》第4,5,6章_第8张图片
    channel-life2.png

    b. ChannelHandler的生命周期


    《Netty 实战》第4,5,6章_第9张图片
    channelhander-life.png

    c. ChannelInboundHandler接口


    《Netty 实战》第4,5,6章_第10张图片
    channelinboundhandler-method.png

    显示资源分配/释放,一些内存位于直接内存,JVM没法管.SimpleChannelInboundHandler会自动释放资源,因此不应该存储指向任何消息的引用.
    d. ChannelOutboundHandler接口


    《Netty 实战》第4,5,6章_第11张图片
    channeloutboundhandler-method.png

    ChannelPromise是ChannelFuture的子类,只有一次状态变更机会(和JS的一样啊)
    e. ChannelHandler适配器
    基本使用了空实现,继承时只需要关心要覆盖的方法
    f. 资源管理
    Netty使用引用计数器来处理池化的ByteBuf,因此调整引用计数器来管理对应的内存资源.
    启动时:-Dio.netty.leakDectectionlevel=ADVANCED进行泄露检测.
    入站消息被消费后,就不会传给下个InboundHandler了.
    出站wreite后就需要release了,不应该在传给下个OutboundHandler了.

  2. ChannelPipeline接口:
    channel与其Pipeline是在创建的时候关联的,无法改变.只能该Pipeline中的Handler.在Pipeline中传递消息时候,会自动判断下一个类型和事件方向是否匹配,不匹配自动跳过


    《Netty 实战》第4,5,6章_第12张图片
    pipeline-handler.png

    a. 修改ChannelPipe的API


    《Netty 实战》第4,5,6章_第13张图片
    pipeline-methods.png

    由于Handler是在EventLoop线程中运行的,所以千万不要编写阻塞代码,否则整个Netty性能都受影响.如果有遗留代码,可以使用EventExecutorGroup新建线程(同样开销大).
    b. 事件触发
    出站/入站都有对应的fire××()方法,调用pipeLine向下个Handler流动.

  3. ChannelHandlerContext
    ctx是Handler和Pipeline之间的关联,与Handler一一对应,从AbstractChannelHandlerContext可知,有prev,next,构成链条的地方.
    a. ChannelHandlerContext使用


    《Netty 实战》第4,5,6章_第14张图片
    channel-relations.png

    实际上Channel或channelPipeLine上的事件是通过ChannelHandlerContext上调用完成的(整个链传播),而直接调用ctx可更加精细控制,只传播到下一个Handler.


    《Netty 实战》第4,5,6章_第15张图片
    ctx-eventline.png
  4. 异常处理:
    a. 入站异常,也会继续流动,直到Pipeline链有人caught处理
    b. 出站异常,返回ChannelFuture->channelFutureListener,关心处理结果的自行判断处理

你可能感兴趣的:(《Netty 实战》第4,5,6章)