前言
Apache HttpAsyncClient 源码分析 前文分析过异步http client的实现。
近日,org.apache.httpcomponents 发布了 http cleint 5,一个项目囊括了过去多个http client,其中就包括HttpAsyncClient 。
http cleint 5的具体实现与旧版类似,详见前文。
本文主要分析异步client的各个配置的含义。
- 依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5 -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.1</version>
</dependency>
</dependencies>
- 样例代码
http-client-5-demo
正文
全部配置
IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
.setSoTimeout(Timeout.ofMilliseconds(250)) // 1.1
.setSelectInterval(TimeValue.ofMilliseconds(50)) // 1.2
.build();
PoolingAsyncClientConnectionManager build = PoolingAsyncClientConnectionManagerBuilder.create()
.setPoolConcurrencyPolicy(PoolConcurrencyPolicy.LAX) // 2.1
.setMaxConnPerRoute(6).build(); // 2.2
Main.client = HttpAsyncClients.custom()
.setIOReactorConfig(ioReactorConfig)
.setConnectionManager(build)
.disableAutomaticRetries() // 3.1
.build();
client.start();
SimpleHttpRequest httpRequest = SimpleHttpRequest.create(Method.GET.name(), "http://127.0.0.1:8080/greeting");
final SimpleHttpRequest request = SimpleRequestBuilder.copy(httpRequest)
.addParameter("name", "124")
.build();
RequestConfig config = RequestConfig.copy(RequestConfig.DEFAULT)
.setConnectTimeout(150, TimeUnit.MILLISECONDS) // 4.1
.setConnectionRequestTimeout(200, TimeUnit.MILLISECONDS) // 4.2
.setResponseTimeout(100, TimeUnit.MILLISECONDS).build(); // 4.3
request.setConfig(config);
final Future<SimpleHttpResponse> future = client.execute(
SimpleRequestProducer.create(request),
SimpleResponseConsumer.create(),
new FutureCallback<SimpleHttpResponse>() {
@Override
public void completed(final SimpleHttpResponse response) {
System.out.println(request + "->" + new StatusLine(response));
System.out.println(response.getBody());
}
@Override
public void failed(final Exception ex) {
System.out.println(request + "->" + ex);
}
@Override
public void cancelled() {
System.out.println(request + " cancelled");
}
});
大致结构
- 我们通过
CloseableHttpAsyncClient
接口使用http client,它的实现类是InternalHttpAsyncClient
。
1.1 http client的ioReactor
字段使用的是DefaultConnectingIOReactor
类。
DefaultConnectingIOReactor
类有两个字段
private final SingleCoreIOReactor[] workers;
private final MultiCoreIOReactor ioReactor;
构造函数中 ioReactor 由 workers 和 执行worker的线程构造。
this.workers[i] = dispatcher;
threads[i] = (threadFactory != null ? threadFactory : THREAD_FACTORY).newThread(new IOReactorWorker(dispatcher));
this.ioReactor = new MultiCoreIOReactor(this.workers, threads);
MultiCoreIOReactor ioReactor
中没有什么重要代码,就是在统一管理SingleCoreIOReactor[] workers
。
SingleCoreIOReactor
类中的主要方法为SingleCoreIOReactor#doExecute
,负责selector.select()
,然后处理事件。
具体分析
IOReactorConfig
1.1 soTimeout
相当于4.3的默认值。如果设置4.3,则使用此timeout;如果设置了4.3,则最终4.3的值生效
1.2 selectInterval
设置select的间隔
用于SingleCoreIOReactor.doExecute()
方法内的
final int readyCount = this.selector.select(this.selectTimeoutMillis);
的selectTimeoutMillis
。
影响select的频率,也会影响timeout的最小精度。
如 设置为 100ms,那么超时中的50ms会被忽略。PoolingAsyncClientConnectionManager
2.1 poolConcurrencyPolicy
STRICT 模式通过加锁的方式对2.2严格计数; LAX 通过cas的方式宽松计数
设置STRICT,会使用StrictConnPool
实现类;
设置LAX ,会使用LaxConnPool
实现类。
2.2 maxConnPerRoute
每个route最多能有多少个connection,具体可见前言中提到的Apache HttpAsyncClient 源码分析一文。
在2.1中的ConnPool实现类的lease()方法中会被使用
HttpAsyncClients
3.1 automaticRetriesDisabled
关闭自动重试RequestConfig
4.1 connectTimeout
建立tcp连接的超时
会被SingleCoreIOReactor.connect()
中用到,用于创建IOSessionRequest
。
进而在InternalConnectChannel.onIOEvent()
方法中检查超时。
4.2 connectionRequestTimeout
从ManagedConnPool (STRICT or LAX)中lease connection。
如果达到maxConnPerRoute,需要在队列中等待的超时时间
4.3 responseTimeout
获取 http respones 的timeout
最后会被赋值到IOSessionImpl
类的socketTimeout
字段。
在抽象类InternalChannel.checkTimeout
方法中被使用,(实现类是InternalDataChannel)。
即selector.select()
后,会检查一下所有的SelectionKey.attachment
,即InternalChannel
的超时。
所以1.2设置的selectInterval值,会影响此超时的精度。