zoukankan      html  css  js  c++  java
  • 心有 netty 一点通!

    一、标准的netty线程模型

    双池合璧:

    1、连接线程池:

    连接线程池专门负责监听客户端连接请求,并完成连接的建立(包括诸如握手、安全认证等过程)。

    连接的建立本身是一个极其复杂、损耗性能的过程,此处使用线程池,能够极大的增加处理客户端连接的能力。

    2、I/O线程池:

    连接线程池会将成功建立的连接注册到后端I/O线程池,由I/O线程池负责对相应连接的网络数据进行读写、编解码处理。

    在实际应用中,我们通常会定义相应的业务消息协议,并选择合适的序列化机制,netty I/O线程池部分根据预设的规则进行数据的编解码。

    二、延伸的业务线程池

     

    其实我们这里说的业务线程池不在网络层处理逻辑里。处理到I/O线程池部分,所需要的请求数据已经处理完毕,涉及具体的业务处理逻辑,比较复杂的,或者时间、性能消耗特别大的,通常我们会单独设置相应的线程池来处理。

    三、netty的极致性能设计

    1、无锁化设计

    I/O线程的内部串行化:

    局部无锁化串行处理,避免多线程切换带来的复杂性及性能损耗(锁竞争、CPU资源分配)。至于对于处理能力的考虑,可以通过调整I/O线程池容量来平衡。

    尽量避免I/O线程和业务线程混淆及切换。

    2、直接内存使用

    TCP接收和发送使用直接内存代替堆内存,避免了数据在堆内存和主内存之间的复制消耗,提升了I/O读取和写入的性能。

     3、transferTo

    依赖于操作系统零拷贝特性直接将缓冲区数据发送到相应的通道。

    传统的方式,先将源文件拷贝到内存,然后由内存写到目的文件。

    netty 利用 NIO FileChannel transferTo方法,通道对通道写数据。

    4、CompositeByteBuf

    组合缓存使用可以像操作单个缓存一样操作多个缓存,避免了传统的操作方式带来的内存复制性能消耗。

    5、内存池使用

    netty支持通过内存池的方式循环利用ByteBuf,避免了频繁的创建,销毁ByteBuf带来的资源及性能损耗。

    ByteBuf byte数据缓冲区,是NIO编程的主要对象。高负载情景下,ByteBuf内存池使用,可以有效降低GC频率。

    PoolArena netty的内存池实现类。PoolArena 是由多个Chunk组成的大块内存区域,每个Chunk由一个多个Page组成。

    Chunk:组织管理Page的内存分配和释放,Page被构建为二叉树形式:

    PoolSubpage:对于小于Page的内存使用,直接在Page中完成分配,每个Page切分为大小相同的多个存储块儿,存储块儿的大小由第一次申请的内存块儿大小决定。

    回收:netty使用状态位标识Chunk及Page内存可用性,Chunk标识二叉树Page节点使用状态;Page标识内部内存块儿的使用状态。

    6、线程安全优化

    合理的使用线程安全容器、原子类等,提升系统的并发处理能力,

    7、引用计数器

    通过引用计数器及时的申请释放不再引用的对象,细粒度的内存管理降低了GC的频率,减少GC带来的时延增大和CPU损耗。

    Netty 4中 ByteBuf 和 ByteBufHolder 引入引用计数器功能(实现ReferenceCounted接口),在特定的对象上跟踪引用的数目。

    引用计数器初始为1。如果对象活动的引用计数器大于0,则不会被释放。当引用计数减少到0,实例将会被释放。这也是 PooledByteBufAllocator 内存池应用的核心特性。

  • 相关阅读:
    beforeEach的应用
    小程序
    betterScroll的应用
    前端规划
    vue中下载文件如pdf及图片
    vue cli3.x项目创建及配置
    python读取excel文件中所有sheet表格:openpyxl模块(二)
    python访问excel基本用法:openpyxl模块(一)
    SQL优化:设置执行计划的显示格式
    sql优化实战:把full join改为left join +union all(从5分钟降为10秒)
  • 原文地址:https://www.cnblogs.com/niejunlei/p/13070107.html
Copyright © 2011-2022 走看看