自适应算法本来我以为看到这位大佬的测试已经是非常有收获了,没想到接下去的闲逛又让我发现了一个更了不得的东西。既然上面分析出来,在QPS比较高的情况下,收益才能抵消被抵消,那么有没有可能实现一个自适应的算法,在QPS较低的时候直接从系统获取,QPS较高时,从缓存获取。果不其然,Sentinel(Java版,版本>1.8.2)已经实现了!issue参考:https:github.comalibabaSentinelpull1746我们捋一下它的实现:我们首先看最核心的...
2022-07-19 10:41:37 5048浏览 0点赞 0回复 0收藏
大家好,我是bin!在上篇文章我为Netty贡献源码且看Netty如何应对TCP连接的正常关闭,异常关闭,半关闭场景发布之后,有很多小伙伴留言给我,问的问题最多的是:“我该如何从零开始参与开源项目?”。看得出来大家对参与开源的热情是非常高涨的,都非常期望为开源社区贡献自己的一份力量。既然是从零开始,那么摆在我们面前有两个大的问题:1.如何找到合适的开源项目参与进来?2.到底该向开源项目贡献些什么?针对第一个问题,我...
2022-07-19 10:41:31 5766浏览 1点赞 1回复 0收藏
加解锁代码位置有讲究根据前面的分析,我们已经有了一个「相对严谨」的分布式锁了。于是「谢霸哥」就写了如下代码将分布式锁运用到项目中,以下是伪代码逻辑:publicvoiddoSomething(){redisLock.lock();上锁try{处理业务.....redisLock.unlock();释放锁}catch(Exceptione){e.printStackTrace();}}❝有没有想过:一旦执行业务逻辑过程中抛出异常,程序就无法执行释放锁的流程。所以释放锁的代码一定要放在finally{}块中。加锁的...
2022-07-19 10:41:14 5158浏览 0点赞 0回复 0收藏
❝可能是最完善的redis分布式锁原理与实战总结,建议收藏redis分布式锁使用SET指令就可以实现了么?在分布式领域CAP理论一直存在。分布式锁的门道可没那么简单,我们在网上看到的分布式锁方案可能是有问题的。「码哥」一步步带你深入分布式锁是如何一步步完善,在高并发生产环境中如何正确使用分布式锁。在进入正文之前,我们先带着问题去思考:•什么时候需要分布式锁?•加、解锁的代码位置有讲究么?•如何避免...
2022-07-19 10:40:47 4921浏览 0点赞 0回复 0收藏
写在前面.....本文是笔者肉眼盯Bug系列的第三弹,前两弹分别是:•抓到Netty一个Bug,顺带来透彻地聊一下Netty是如何高效接收网络连接的,在这篇文章中盯出了一个在Netty接收网络连接时,影响吞吐量的一个Bug。•抓到Netty一个隐藏很深的内存泄露Bug详解Recycler对象池的精妙设计与实现,在这篇文章中盯出了一个Netty对象池在多线程并发回收对象时可能导致内存泄露的一个Bug。而在本篇文章中笔者又用肉眼盯出了Netty在处...
2022-07-19 10:39:50 5469浏览 0点赞 0回复 0收藏
2.Netty对TCP连接正常关闭的处理privatevoidcloseOnRead(ChannelPipelinepipeline){判断服务端连接接收方向是否关闭,这里肯定是没有关闭的if(!isInputShutdown0()){if(isAllowHalfClosure(config())){.....省略TCP连接半关闭处理逻辑.......}else{如果不支持半关闭,则服务端直接调用close方法向客户端发送fin,结束closewait状态进如lastack状态close(voidPromise());}}else{.....省略TCP连接半关闭处理逻辑.......}}众所周知T...
2022-07-19 10:39:32 1.1w浏览 0点赞 0回复 0收藏
2.1.5Channel的关闭image.pngprepareToClose方法返回的closeExecutor是用来执行Channel关闭操作的,当我们开启了SOLINGER选项时,closeExecutorGlobalEventExecutor.INSTANCE,避免了Reactor线程的阻塞。由GlobalEventExecutor负责执行doClose0方法关闭Channel底层的Socket,并通知closeFuture关闭结果。privatevoidclose(finalChannelPromisepromise,finalThrowablecause,finalClosedChannelExceptioncloseCause,finalbooleann...
2022-07-19 10:39:07 7802浏览 0点赞 0回复 0收藏
3.TCP连接的异常关闭image.png在本文前边的内容中,我们介绍了TCP数据包中的SYN包,FIN包,ACK包的使用场景,它们都是通过TCP首部协议中的8位控制位来标识,不同的控制位代表不同的含义。第二小节介绍的内容均属于TCP在正常情况下进行的连接的建立,发送数据,关闭连接。而现实中情况往往是复杂的,TCP连接不可能总是处于正常的状态,那么当TCP连接出现异常时,就需要有一种机制让我们来强制关闭连接,这个就是本小节要介绍的RS...
2022-07-19 10:29:15 5347浏览 0点赞 0回复 0收藏
4.Netty对RST包的处理同TCP正常关闭收到FIN包一样,当服务端收到RST包后,OPREAD事件活跃,Reactor线程再次来到了AbstractNioByteChannelread方法处理OPREAD事件。publicabstractclassAbstractNioByteChannelextendsAbstractNioChannel{Overridepublicfinalvoidread(){finalChannelConfigconfigconfig();..........省略连接半关闭处理..................省略获取allocHandle过程.......ByteBufbyteBufnull;booleanclosefalse;tr...
2022-07-19 10:28:39 4949浏览 0点赞 0回复 0收藏
6.主动关闭方发起TCP半关闭流程在TCP半关闭的场景下,主动关闭方需要调用shutdownOutput方法向被动关闭方发送FIN开始TCP半关闭流程。在本小节的示例中,客户端可以在自己的ChannelHandler中调用Channel的shutdownOutput方法来发起TCP半关闭流程。SocketChannelsc(SocketChannel)ctx.channel();sc.shutdownOutput();下面我们就来分析下在netty中对于shutdownOutput的实现。publicclassNioSocketChannelextendsAbstractNioByteCha...
2022-07-19 10:27:41 6241浏览 0点赞 0回复 0收藏
8.提交PR,修复Bug笔者首先向Netty社区提交了一个Issue,在Issue中详细为社区人员描述了这个Bug产生的原因。也就是上一小节中的内容。Issue:https:github.comnettynettyissues11981image.pngSOLINGERHalfClosureBug.png随后笔者按照《7.啊哈!!Bug!!》小节中介绍的修复思路为这个Issue提交了修复PR,PR:https:github.comnettynettypull11982PR.png笔者修复后的ShutdownOutput流程逻辑如下:image.png编写单元测试,然后信心...
2022-07-19 10:27:19 6629浏览 0点赞 0回复 0收藏
4.2flush事件的处理客户端channelpipeline结构.png最终flush事件会在pipeline中一直向前传播至HeadContext中,并在HeadContext里调用channel的unsafe类完成flush事件的最终处理逻辑。finalclassHeadContextextendsAbstractChannelHandlerContext{Overridepublicvoidflush(ChannelHandlerContextctx){unsafe.flush();}}下面就真正到了Netty处理flush事件的地方。protectedabstractclassAbstractUnsafeimplementsUnsafe{Overridep...
2022-07-19 10:26:51 6750浏览 0点赞 0回复 0收藏
5.终于开始真正地发送数据了!来到这里我们就真正进入到了Netty发送数据的核心处理逻辑,在《Netty如何高效接收网络数据》一文中,笔者详细介绍了Netty读取数据的核心流程,Netty会在一个readloop中不断循环读取Socket中的数据直到数据读取完毕或者读取次数已满16次,当循环读取了16次还没有读取完毕时,Netty就不能在继续读了,因为Netty要保证Reactor线程可以均匀的处理注册在它上边的所有Channel中的IO事件。剩下未读取的数...
2022-07-19 10:26:35 1.2w浏览 0点赞 0回复 0收藏
6.处理Socket可写但已经写满16次还没写完的情况OverrideprotectedvoiddoWrite(ChannelOutboundBufferin)throwsException{SocketChannelchjavaChannel();intwriteSpinCountconfig().getWriteSpinCount();do{.........将待发送数据转换到JDKNIOByteBuffer中.........intnioBufferCntin.nioBufferCount();switch(nioBufferCnt){case0:这里主要是针对网络传输文件数据的处理FileRegionwriteSpinCountdoWrite0(in);break;case1:{.......
2022-07-19 10:25:47 6494浏览 0点赞 0回复 0收藏
8.writeAndFlush在我们讲完了write事件和flush事件的处理过程之后,writeAndFlush就变得很简单了,它就是把write和flush流程结合起来,先触发write事件然后在触发flush事件。下面我们来看下writeAndFlush的具体逻辑处理:publicclassEchoServerHandlerextendsChannelInboundHandlerAdapter{OverridepublicvoidchannelRead(finalChannelHandlerContextctx,finalObjectmsg){此处的msg就是Netty在readloop中从NioSocketChannel中读...
2022-07-19 10:25:11 7620浏览 0点赞 0回复 0收藏
4.flush从前面Netty对write事件的处理过程中,我们可以看到当用户调用ctx.write(msg)方法之后,Netty只是将用户要发送的数据临时写到channel对应的待发送缓冲队列ChannelOutboundBuffer中,然而并不会将数据写入Socket中。而当一次read事件完成之后,我们会调用ctx.flush()方法将ChannelOutboundBuffer中的待发送数据写入Socket中的发送缓冲区中,从而将数据发送出去。publicclassEchoServerHandlerextendsChannelInboundHandle...
2022-07-18 17:33:24 7818浏览 0点赞 0回复 0收藏
3.3.5向ChannelOutboundBuffer中缓存待发送数据在介绍完ChannelOutboundBuffer的基本结构之后,下面就来到了Netty处理write事件的最后一步,我们来看下用户的待发送数据是如何被添加进ChannelOutboundBuffer中的。publicvoidaddMessage(Objectmsg,intsize,ChannelPromisepromise){EntryentryEntry.newInstance(msg,size,total(msg),promise);if(tailEntrynull){flushedEntrynull;}else{EntrytailtailEntry;tail.nextentry;}tail...
2022-07-18 17:33:15 6920浏览 0点赞 0回复 0收藏
3.3ChannelOutboundBufferChannelOutboundBuffer其实是一个单链表结构的缓冲队列,链表中的节点类型为Entry,由于ChannelOutboundBuffer在Netty中的作用就是缓存应用程序待发送的网络数据,所以Entry中封装的就是待写入Socket中的网络发送数据相关的信息,以及ChannelHandlerContextwrite方法中返回给用户的ChannelPromise。这样可以在数据写入Socket之后异步通知应用程序。此外ChannelOutboundBuffer中还封装了三个重要的指针...
2022-07-18 17:32:59 7393浏览 0点赞 0回复 0收藏
3.2HeadContextfinalclassHeadContextextendsAbstractChannelHandlerContextimplementsChannelOutboundHandler,ChannelInboundHandler{Overridepublicvoidwrite(ChannelHandlerContextctx,Objectmsg,ChannelPromisepromise){unsafe.write(msg,promise);}}write事件最终会在pipeline中传播到HeadContext里并回调HeadContext的write方法。并在write回调中调用channel的unsafe类执行底层的write操作。这里正是write事件在pipeline...
2022-07-18 17:32:29 5973浏览 0点赞 0回复 0收藏
3.write方法发送数据write事件传播流程.pngabstractclassAbstractChannelHandlerContextimplementsChannelHandlerContext,ResourceLeakHint{OverridepublicChannelFuturewrite(Objectmsg){returnwrite(msg,newPromise());}OverridepublicChannelFuturewrite(finalObjectmsg,finalChannelPromisepromise){write(msg,false,promise);returnpromise;}}这里我们看到Netty的写操作是一个异步操作,当我们在业务线程中调用channelHand...
2022-07-18 17:32:06 7498浏览 0点赞 0回复 0收藏