这里暂且仅关注连接池的实现,部分涉及Netty的channel输入输出处理、哈希轮定时器算法、事件轮询方式的区别,又或者信号量的使用等等,以后有机会会单独拿出来详解。
由于是基Netty的实现的,所以连接池实际上就是对channel的管理控制,有趣的是整个管理只用到了信号量+一个定时检测器,略微复杂的也就定时检测的逻辑,其实现方式简单且很好理解,不像httpclient里各种队列各种信号量难以理解。
先上一个简单的例子,事实上使用起来也不复杂。
先看看DefaultAsyncHttpClientConfig类的配置参数,这里只列出本文所需要的参数。有一点值得提一下,如果想了解Java怎么像clojure或者scala一样创建不可变对象,可以看看这个类的写法。
就从这里开始,开头主要实例化ChannelManager和NettyRequestSender以及Timer三个重要组件,NettyRequestSender用于发送请求以及向ChannelManager索取channel使用权,Timer则负责另外两个组件给他的检测任务。
这里是重中之重,网络配置、连接池、IO线程池、轮询方式都是在这儿产生的。
实例化完ChannelManager后,就轮到请求发送器,这里先看看所需要的参数,具体执行的方法在后面说。
一切工作准备就绪,现在可以请求了!怎么构建请求就不打算讲了,可以自行阅读RequestBuilderBase类。执行execute()方法,正式开始请求,往下看DefaultAsyncHttpClient.executeRequest()怎么创建连接的。
OK~~上面列出NettyRequestSender需要什么参数,现在再来看看怎么做的? 下面的方法中,重点关注sendRequestWithNewChannel,它包括了如何新建channel、连接,抢占信号量
NettyChannelConnector负责对远程IP创建连接,一旦连接成功,NettyConnectListener就会调用requestSender向服务端发送数据。
连接成功,就来到这里,拿到channel,准备向服务器发送数据!
读取数据一切顺利后,就会走下面这个私有方法,将channel送入channelpool里,等待生命的结束!
tryToOfferChannelToPool 是ChannelManager的方法,主要将依然活跃的channel送入生命倒数器中,还记得connectionTtl么,这个参数在这就起作用了!
到这里,关于channel已经接近尾声了,细心的童鞋可能发现,信号量呢?!不用释放么?!其实在关闭channel的时候,已经释放了,这是因为 ChannelGroup 的作用,在将channel注册(add方法)到group的时候,已经在其上面加了关闭的监听器,一旦close就执行remove,实例化 ChannelGroup 时已经将remove(channel)重写,可以倒回去看是不是已经释放了信号量,也可以看看 ChannelGroup 源码是不是在add时候添加了监听器。
不过,这里只是接近尾声,没意味就结束了,还有存活的channel被塞到 ChannelPool 进行生命的倒计时
这里才是channel的终结!!!
channel被终结了,但有些还存活的channel还在请求的路上,还有很重要的两点没说到,就是 请求超时 和 读取超时。 每个NettyResponseFuture都持有一个TimeoutsHolder来计算 requestTimeout 和 readTimeout 是否过期。在ResponseFuture获取连接后,以及获取成功向服务器发送数据后,都会分别启动请求超时和读取超时两个定时器。通过阅读源码,可以发现 requestTimeout 其实是包括了 readTimeout,如果请求剩余时间小于读取超时时间时,startReadTimeout是不会启动readTimeout定时器的。下面只贴上TimeoutsHolder的部分源码,RequestTimeoutTimerTask和ReadTimeoutTimerTask可以自行阅读。
对于这两个参数,需要说明一点就是,一旦超时过期,channel和future都会被close掉,如果读超设置比请超长则是无意义的,只会以requestTimeout为准。
最后最后最后。。。
来总结一下ahc的连接池实现,很明显的一点整个过程都是对Channel的管理,而且对于连接的抢占则使用了Semaphore,这再方便不过了!!!对于信号量的释放,Netty的ChannelGroup有很大的功劳,它提供了最优雅的方式关闭channel并且释放信号量。除此之外,一堆的超时限制任务需要一个定时任务容器执行,Netty又提供了一个在面对大量任务依然稳坐泰山的HashedWheelTimer,有机会专门来说说这一个。还有就是DefaultChannelPool对存活时间的检测,实在是通俗易懂,而且基于前面说的几点,实现起来也相当方便。
如果遇到基于netty的网络编程开发,对于连接资源的管理ahc确实提供了一套不错的思路,不仅对客户端,服务端也是可以试一试的!
http://www.voidcn.com/article/p-cethcmyr-bot.html
到此这篇redis查看端口(redis查看客户端连接数)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/hd-yjs/26775.html