Netty源码分析之设计模式在Netty框架中的应用
如果你对设计模式不是很熟悉,建议补习一下设计模式再来阅读本章的内容。本章主要分析设计模式的应用案例,不对设计模式本身做详细讲解。1.1 单例模式源码举例
单例模式要点回顾如下。
(1)一个类在任何情况下只有一个对象,并提供一个全局访问点。
(2)延迟创建。
(3)避免线程安全问题。
Netty中的单例模式应用非常广泛,单例模式本身也比较简单,下面列举MqttEncoder类,采用饿汉式单例的写法。饿汉式单例最大的优点就是简单,绝对线程安全。具体代码如下。
1.2 策略模式源码举例
策略模式要点回顾如下。
(1)封装一系列可相互替换的算法家族。
(2)动态选择某一个策略。
Netty在根据CPU核数分配线程数量的一个优化时,如果是2的平方则采用PowerOfTwoEventExecutorChooser来创建EventExecutorChooser,如果不是2的平方则采用GenericEventExecutorChooser来创建EventExecutorChooser,这里用的是三元运算选择策略,具体代码如下。
1.3 装饰者模式源码举例
装饰者模式要点回顾如下。
(1)装饰者和被装饰者实现同一个接口。
(2)装饰者通常继承被装饰者,同宗同源。
(3)动态修改、重载被装饰者的方法。
从Netty的ByteBuf类结构图可以看到,ByteBuf的直接实现类有五个,忽略WrappedByteBuf这个类,其实直接实现类有四个。为什么要忽略掉WrappedByteBuf呢?因为它是ByteBuf装饰者的基类,本身没有任何实现功能。来看WrappedByteBuf的代码,主要功能就是保存被装饰者的引用。
具体的装饰者,继承上面的装饰者的顶级类,在自己的构造函数中接收ByteBuf的类型的参数,并把它传递给它的父类,用户在调用装饰者时,会把创建的最上面的四种待装饰的组件类以构造方法的形式传递进去,整个体系就运行起来了。而且装饰者可以按照自己的需求重写父类的方法,或者在现在的基础上添加新的方法调用进行增强。例如UnreleasableByteBuf类,重写了release()方法,并返回false表示UnreleasableByteBuf不支持被释放。
再比如SimpLeakAwareByteBuf类,从字面意思来看,其实是一个内存泄露感知的ByteBuf,同样继承自WrappedByteBuf。从构造方法来看,其构造参数多了一个ResourceLeak,主要用于对内存泄露的跟踪。主要差异在于增加了release()方法,代码如下。
看到上面的代码,还是来关注release()方法。它调用release()方法,根据返回结果额外增加了一个资源泄露的监控行为。1.4 观察者模式源码举例
观察者模式要点回顾如下。
(1)两个角色:观察者和被观察者。
(2)观察者订阅消息,被观察者发布消息。
(3)订阅则能收到消息,取消订阅则收不到消息。
Netty里面的观察者和被观察者模式一般用Promise和Future来实现。项目中用得比较多的一个方法就是channel.writeAndFlush()方法。当调用channel.writeAndFlush()方法的时候,实际上就是创建了一个被观察者ChannelFuture,来看源码。
writeAndFlush()方法的返回值是ChannelFuture。当调用ChannelFuture的addListener()方法的时候,其实就是往ChannelFuture中添加被一个ChannelPromise,继续往下跟踪源码。
上面的writeAndFlush()方法还有一个重载方法,其中一个参数就是ChannelPromise,通常情况下Future和Promise是成对出现的。我们发现ChannelPromise就是ChannelFuture的子类,在Promise中定义了非常多的回调方法,提供给用户去重载,用户用自己的逻辑通常实现各种Listener接口来重载达到回调通知的目的。1.5 迭代器模式源码举例
迭代器模式要点回顾如下。
(1)实现迭代器接口。
(2)实现对容器中的各个对象逐个访问的方法。
Netty里面的CompositeByteBuf这个零拷贝的实现,就使用了迭代器模式。首先看一段代码。
这段代码把两个ByteBuf添加到一起,forEachByte就是实现了迭代器模式。那么为什么说它是零拷贝呢?
我们找到forEachByte()的实现,在AbstractByteBuf里面,有下面这样一段代码。
从readerIndex开始读,读到writeIndex。继续跟进forEachByteAsc0()方法,查看源码。
继续看getByte()方法的实现,找到CompositeByteBuf类的实现。
先找到Index对应的Component,然后迭代的时候直接返回Component的Byte内容,就实现了零拷贝。其他的ByteBuf如果迭代的话,可能会把所有的数据都拷贝一遍。1.6 责任链模式源码举例
责任链是指多个对象都有机会处理同一个请求,从而避免请求的发送者和接收者之间的耦合关系。然后,将这些对象连成一条链,并且沿着这条链往下传递请求,直到有一个对象可以处理它为止。在处理过程中,每个对象只处理它自己关心的那一部分,不相关的部分可以继续往下传递,直到链中的某个对象不想处理,可以将请求终止或丢弃。
责任链模式要点回顾如下。
(1)需要有一个顶层责任处理接口。
(2)需要有动态创建链、添加和删除责任处理器的接口。
(3)需要有上下文机制。
(4)需要有责任终止机制。
Netty的Pipeline就是采用了责任链设计模式,底层采用双向链表的数据结构,将链上的各个处理器串联起来。客户端每一个请求到来,Netty都认为是Pipeline中所有的处理器都有机会处理它。因此,对于入栈的请求,全部从头节点开始往后传播,一直传播到尾节点(来到尾节点的msg才会被释放)。
Netty的责任链模式中的组件如下。
(1)责任处理器接口ChannelHandler。
(2)添加删除责任处理器的接口ChannelPipeline。
(3)上下文组件ChannelHandlerContext,可获得用户记需要的数据。
(4)终止责任链的ctx.fireXXX()方法,可终止传播事件。
Pipeline中所有的Handler为顶级抽象接口,它规定了所有的Handler统一要有添加、移除、异常捕获的行为。
Pipeline中的Handler被封装进了上下文中。通过上下文可以轻松获取当前节点所属的Channel及其线程执行器。
责任终止机制包括如下内容。
(1)Pipeline中的任意一个节点,只要不手动往下传播,这个事件就会在当前节点终止传播。
(2)对于入栈数据,默认会传递到尾节点进行回收,如果不进行下一步传播,事件就会终止在当前节点。
(3)对于出栈数据,头节点使用Unsafe对象,把数据写回客户端也意味着事件的终止。
底层事件的传播使用的就是针对链表的操作,如AbstractChannelHandlerContext类的findContextInbound()方法。
1.7 工厂模式源码举例
工厂模式的要点就是将创建对象的逻辑封装起来。
我们最先接触ReflectiveChannelFactory就是专门用来创建Channel的工厂,它接收一个Class对象,然后调用Class的newInstance()方法,将创建好的对象返回去。
Netty中的设计模式应用非常多,这里不再一一列举,希望大家花时间去探索,这样才能够有更多的收获。本章旨在为大家打开深入探索Netty的大门,有不妥之处请纠正交流。
全球第一艘5G大型邮轮将起航图源中船嘉年华大型邮轮被称为造船行业皇冠上最耀眼的明珠,而最先进的现代通信技术,正将这颗明珠擦拭得更加光华夺目。1月12日,上海电信与中船嘉年华邮轮有限公司(简称中船嘉年华)旗下爱
雷军曾经吹下的牛三年做到全球第一,现在实现了吗?现实很打脸经常看小米发布会的小伙伴们,肯定或多或少听到过雷军吹牛,比如十个季度重返国内第一三年做到全球第一全面对标iPhone等等,但随着时间的流逝,很多人淡忘了雷军曾经吹下的牛,到目前为止
以下看似养生实则伤身的知识,请大家仔细阅读现在的生活越来越好了,大家越来越注意健康,注意养生了,然而呢,有些看似健康的生活方式,其实对身体是有害的,下面这些大家经常做的事情,你以为是养生,其实可能是在养病。知识一多走路,多
24亿年前,寒冬持续3亿年,大雪冰封地球,科学家或再次发生综述地球刚刚诞生的时候是什么样子的,诞生之初就有了氧气吗,初始形态的地球也像现在一样有水有阳光吗?原始地球并不是现在意义上的地球,那时候,地球上的环境与现在截然不同,地球上的温度非
宝马在华豪取四连冠BBA全力以赴电动化来源中国经济网姜智文2022年,宝马以79。2万辆的成绩,连续第四年折桂高档车市场,奔驰与之差距进一步缩小。对于2022年在华表现,宝马和奔驰不约而同地提到了韧性尽管挑战重重,两者
谁说带娃出行,一定鸡飞狗跳,新5008让春节出游更轻松自在以前过年,一家人围坐在电视机旁边,看着春节联网晚会,享受其乐融融的团圆时刻。现在过年,人们越想追寻自由,趁假期好好放松下,去别的地方,去体验不同的风俗和年味。于是,春节自驾游就成为
一骑红尘殉原创夏天的夜,多了几分的喧嚣,地头的田蛙不知道是在什么时候开始,弹奏起了交响。一桌,一椅,一茶,一人独坐在小院中轻摇着折扇,抬头看着漫空的星辰,偶尔一颗流星从天边划过,闭上眼寄上一份祷
手握一百多万想买4门5座纯电动轿车?浅析宝马i7首年用车成本买车要考虑自己的经济条件,根据自己的收入水平选择适合自己的车型。对于很多工薪阶层来说,月收入五六千元,在生活成本的支出上就已经捉襟见肘了。所以在考虑买车时,除了新车的售价之外,用车
戴德蒙炮轰斯波那个老家伙,一直教我事,指指点点让我很不自在NBA常规赛拉开序幕,热火队险胜雷霆队。热火球员戴德蒙在场上打得十分憋屈,教练层一直对戴德蒙指指点点的,没想到热火队因戴德蒙直接爆发内讧,看呆雷霆年轻人。据热火记者BarryJac
道不尽红尘奢恋不看好的当代梁祝读罢这个悲惨的新闻,我赞同网友评论为人妻你可以悲伤,为人母,不能这么自私。但说不出一句责备的话,你的痛别人都不能感同身受,愿她一路走好。如果真的爱你丈夫,应该把你们的孩子好好培养成
散文拥有一颗淡然自在的心,活得更快乐作者子墨人生的路上,风雨兼程,穿越春夏秋冬,淡然四季更迭,很多时候,我们都忙着生活,忘记了欣赏身边的风景,而让自己失去了太多的快乐。晨起暮落的生活中,很少有时间去思考这个问题,忍受