1.Netty的flush优化handler——FlushConsolidationHandler

Netty的实现更复杂一些,对于用单独线程池处理业务的场景,有一些特殊的处理和优化,比如如果异步处理的时候,即channelReadComplete比channelRead结束的要早,所以在flush调用的时候,readInProgress已经是false了,然后根据用户决定是否开启对于异步的强化来决定是直接flush还是走consolidateWhenNoReadInProgress,如果consolidateWhenNoReadInProgress为true(开启增强),那么就用次数是否到达阈值来决定立即刷新还是延时刷新。

我们可以写一个demo来尝试一下,这里我们为业务单独指定线程池,同时开启异步增强

关于标志位,首先channelRead方法中会把readInProgress置为true,代表正在读,还没有执行channelReadComplete方法,此时flush是同步,因为还没到channelReadComplete的时候。

然后channelReadComplete方法中把它又置为false,说明channelReadComplete方法执行完了,此后的flush都是异步了,因为业务执行慢,错过了channelReadComplete。

再看这些count,这里第一次flushPendingCount++是1,不满足阈值,所有走到scheduleFlush之中,虽然该方法中没有延时,但是毕竟是单独提交任务,所以给了其它请求write的机会,所以也就有可能节省flush的次数,这里为了让scheduleFlush更慢,我们在这个断点处停留一下,相当于卡住,不让它schedule(调试技巧)。同时客户端因为又发了请求,所以这第二个请求又会触发到这里的flush

可以看到会走到代码断点处,这里就会触发flushNow,这里会进行flush,并取消掉scheduleFlush这个任务,说明这两个请求的flush合并为一个flush了,节省了一次flush。

2.Cassandra的flush优化——Dispatcher#Flusher

我们参考Cassandra的实现,https://github.com/PaytmLabs/cassandra/blob/master/src/java/org/apache/cassandra/transport/Message.java,去除Cassandra的编解码和连接的部分,自己写一个flush的优化器

然后和Netty的Consolidation对比一下,可以发现Cassandra的这个优化器的思路更为简单清晰。它就是利用了队列来保存待flush的内容,在达到flush条件的时候把队列里存储的需要flush的内容一次性flush出去。

flush的条件

flush的条件有两个,一个是runsSinceFlush,还有一个是flushed的元素个数,两者有其一满足就可以flush,这样可以防止两种场景:

①请求量很大,在run方法执行3次以前,flushed中已经积攒了太多的需要flush的内容,所以要设置flushed的阈值

②请求量很小,flushed很久才会达到阈值,这样要等很久才能把之前积攒的消息flush出去,会有很大延时,所以要设置runWithNoWork的阈值

结合这两个设置就可以避免这两种极端情况出现了。然后它还可以通过为eventLoop这个executor添加延时任务的方式循环调用该run方法,可以更精细的控制这个flush的流程。

自毁功能

然后这个flusher还有一个自毁功能,如果runsWithNoWork超过5次,说明连续5次都没有发现要flush的内容,那么就判断是否要结束该run方法,并不再schedule。

这里有两个判决条件:待flush的队列是否为空,running.compareAndSet(false,true)是否失败,两者满足其一就可以结束run执行并不再schedule。

队列为空比较容易理解,因为没有待flush的任务了。那么running.compareAndSet(false,true)是否失败是什么意思呢?我们看到Flusher的start方法中,会判断running标志位,如果running是false,同时running.compareAndSet(false,true)成功,就可以将该run作为task用EventLoop来执行。那么假设这里有两个线程,线程A执行到runsWithNoWork超过5次的逻辑了,那么它会先将running设置为false,然后执行running.compareAndSet(false,true),另一个线程B执行到start方法中的running,首先会判断它是false,然后也执行running.compareAndSet(false,true),这两个只会有一个成功。

如果线程A成功了,那么说明线程B的start没有成功,但是确实又有任务需要添加到flush的队列中,所以run方法不能就此终止,所以这里逻辑也是和这里的分析吻合的,这时不能return,要继续schedule该run方法。

如果线程A没成功,那么说明线程B的start成功了,既然已经成功又为EventLoop添加了该run方法这个任务,那么A线程正在执行的任务就没必要保留了,那么这里的逻辑也和分析吻合,这时就会return,结束run方法,同时不再schedule。

3.总结

综上,可以看出Cassandra的flush优化实现思路更加清晰简单,但简单的同时又不失全面,可以说考虑各种极端情况和场景,并且通过参数的可配置,让用户可以定制flush的控制逻辑,如果有flush优化场景的工程可以借鉴使用。

Netty第二章 2020 3-9 Netty源码之flush优化相关推荐

  1. Netty第二章 2020 7-4——Netty在Dubbo中的应用(3)关于单一长连接

    dubbo中单一长连接的理解和常见误区 1.低版本dubbo dubbo默认是单一长连接,那么这个默认在哪里,长连接又是什么意思,单一长连接又是什么意思呢? 首先dubbo底层用的是netty,所以长 ...

  2. Netty实战:Springboot+Netty+protobuf开发高性能服务器 (附源码下载)

    Springboot-cli 开发脚手架系列 Netty系列:Springboot使用Netty集成protobuf开发高性能服务器 文章目录 Springboot-cli 开发脚手架系列 简介 1. ...

  3. 老李推荐:第14章4节《MonkeyRunner源码剖析》 HierarchyViewer实现原理-装备ViewServer-端口转发 1...

    老李推荐:第14章4节<MonkeyRunner源码剖析> HierarchyViewer实现原理-装备ViewServer-端口转发 在初始化HierarchyViewer的实例过程中, ...

  4. 老李推荐:第5章5节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 获取系统服务引用 1...

    老李推荐:第5章5节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 获取系统服务引用 上一节我们描述了monkey的命令处理入口函数run是如何调用optionPro ...

  5. 老李推荐:第3章3节《MonkeyRunner源码剖析》脚本编写示例: MonkeyImage API使用示例 1...

    老李推荐:第3章3节<MonkeyRunner源码剖析>脚本编写示例: MonkeyImage API使用示例 在上一节的第一个"增加日记"的示例中,我们并没有看到日记 ...

  6. 老李推荐: 第8章4节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-启动AndroidDebugBridge 1...

    老李推荐: 第8章4节<MonkeyRunner源码剖析>MonkeyRunner启动运行过程-启动AndroidDebugBridge 上一节我们看到在启动AndroidDebugBri ...

  7. 老李推荐:第6章1节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览 1...

    老李推荐:第6章1节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览 在上一章中我们有简要的介绍了事件源是怎么一回事,但是并没有进行详细的描述.那么往下的这几个 ...

  8. 老李推荐:第6章6节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-命令队列...

    老李推荐:第6章6节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-命令队列 事件源在获得字串命令并把它翻译成对应的MonkeyEvent事件后,会把这些事件 ...

  9. 老李推荐: 第3章2节《MonkeyRunner源码剖析》脚本编写示例: MonkeyDevice API使用示例 1...

    老李推荐: 第3章2节<MonkeyRunner源码剖析>脚本编写示例: MonkeyDevice API使用示例 上一节我们学习了如何通过MonkeyRunner这个类的静态方法wait ...

最新文章

  1. 【复盘】如何培养小朋友的编程能力?
  2. apache ignite_Apache Ignite,Hazelcast,Cassandra和Tarantool之间的主要区别
  3. 以下表示中 不能用作c语言常量的是0UL,C语言笔试卷.doc
  4. DOS批处理中%cd%和%~dp0的区别
  5. java 登陆系统设计_Java 程序设计——登录系统
  6. 数据层处理和性能优化
  7. 如何自学成为程序员?
  8. 金融科技大数据产品推荐:金蜂巢大数据集成与脱敏系统
  9. 爬虫学习---基础操作--抽屉新热榜自动点赞与豆瓣自动统一短评
  10. Matplotlib 绘图 (二)
  11. Linux命令--arp--使用/实例
  12. 第六章 样本与抽样分布
  13. gitblit+jenkins本地服务
  14. Java JDK 下载官方网站
  15. 区块链技术,模仿B特币,java模拟区块链技术,(摘自GitHub)
  16. 解决Cleartext HTTP traffic to 01.minipic.eastday.com not permitted
  17. 数据分析平台页面设计_平台设计剖析
  18. 小米node2红外_Kubernetes监控在小米的落地
  19. PHP 验证码 浅析
  20. 关于虚拟现实叙事方式的终极入门指南

热门文章

  1. UIPATH 结合 Python 识别 PDF 中的表格
  2. 关于数字证书链的一点认知
  3. 大地水准面 地球椭球体 大地基准面 地图投影理解
  4. 设计n位乘加器(先乘后加)Design a n-bit multiplier (firstly multiply and then add)
  5. element ui 级联选择器,渲染后不显示数据
  6. 波前边缘检测 Wavefront Frontier Detector
  7. Games101-课程15笔记
  8. 水上乐园设备的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  9. wp7编程环境配置(包含xp下安装)
  10. linux实验报告 dns 新增域名,Linux实验报告DNS及虚拟主机.docx