天天看点

HttpAsyncClient的连接池使用

代码示例

流程分析

简要流程总结如下:

httpasyncclient有一个abstractmultiworkerioreactor和abstractioreactor,

前者和后者类似于netty的bossgroup和workergroup, abstractmultiworkerioreactor负责channel的连接, abstractioreactor负责channel的读写

先要明白连接池的结构

abstractnioconnpool 下各个变量的含义

1. 发起请求

 a. 根据请求route查看连接池, 如果连接池不为空, 直接返回跟池中connection绑定的future,

并把该conn放入leased列表

 b. 如果因为某些原因导致当前请求无法取得连接, 但是没有发生致命错误的, 请求将被放入一个 leasing 列表,

这个列表会在后续动作中被取出来做连接重试

 c. 如果实在连接过程中出现了移除等不可恢复的错误, 则将request标记为completed, 退出方法后调用firecallback,

进行回调清理, 这次请求就算是失败结束了

 d. 如果是因为连接池没有可用连接, 但是可以新建连接的情况, 则会将request 加入pending列表, 并调用

selector的wakeup()方法,

selector在wakeup以后会使用abstractmultiworkerioreactor(bossgroup)来进行连接操作,

并注册到selector中, 后续的connectable事件监听和channel连接成功注册也是由他完成的

2. abstractioreactor监听读写事件

3. 通过decoder检测response已经完成, 最后将连接release到连接池中, 此时将连接从leased列表除去,

并加入到available中

调用

请求开始, 里面会调用 execute(request, new basichttpcontext(), callback)

context 代表了一次请求的上下文, 里面实际上就是一个用来存储 attribute 的结构, 默认的实现 basichttpcontext

实际上就是一个 concurrenthashmap

context 是可以嵌套的, 代码如下

接着看执行流程

这里会通过原来的请求信息生成一个requestproducer跟responseconsumer,

默认会调用httpasyncclient的internalhttpasyncclient的实现, 如下

 这里通过生成一个exchangehandler来实现请求开始, 查看 handler.start()

 接着往下

再看nhttpclientconnectionmanager下的

它调用了poolingnhttpclientconnectionmanager的实现

看 abstractnioconnpool 的 lease 方法

这里主要涉及到连接池 abstractnioconnpool

以及连接池下得实际存储连接的 routespecificpool, 

然后开始分析连接流程

看看defaultconnectingioreactor的connect方法

在abstractmultiworkerioreactor中有一个execute()方法

首次连接的时候, 触发的是 defaultconnectingioreactor 的 processevents 方法

接下来看连接成功后的ioreactor如何处理, 如下 baseioreactor 的 execute 方法

这个就跟abstractmultiworkerioreactor类似, 只不过两个人的兴趣集事件不太一样, 看看 abstractioreactor

的实现类 baseioreactor就知道了

它实际上只会处理 read 跟 write 事件

这里特别注意一下 abstractnioconnpool requestcomplete 并不是整个请求结束, 而是连接成功的意思,

看看他的调用的地方和触发的东西

最开始他是从 abstractioreactor 的processnewchannels中来的, 这个方法在execute里被触发

看看连接池 abstractnioconnpool 的completed 方法做了什么

主要做的事情就是设置了一下连接的sotimeout, 还有就是将连接从 pending列表移到了 lease 集合

最后, 来看看 连接是如何归还的

通过对abstractnioconnpool的release方法的跟踪, 最后找了还是在 baseioreactor 监听到 readable

时间的时候, 调用了httpasyncrequestexecutor的inputready

方法

当检测到response已经完了, 就会进入complete流程, 最后回到releaseconnection流程,

最后到达连接池的release