apache http async client

时间:2018-05-01 10:10:50

标签: asynchronous io apache-httpclient-4.x nonblocking

我正在使用Apache HTTP异步客户端发出http请求(通过使用来自Kafka总线的数据)并处理回调中的响应。

我在日志中发现了一些有趣的回调行为,并想知道hwy就是这样。

以下是代码的一部分(使用来自kafka和make http请求的数据):

    while (true) {
        ConsumerRecords<String, MyMessage> records = kafkaConsumer.poll(1000);
        if (records.isEmpty()) {
            logger.info("Polling Empty ....");
            continue;
        }

        int numberOfRecords = records.count();
        final CountDownLatch batchLatch = new CountDownLatch(numberOfRecords);
        for (ConsumerRecord<String, MyMessage> record: records) {
            final HttpPost request = new HttpPost(endpoint);
            // set headers
            // set entity
            request.setEntity(messageToEntity(record.value()));
            httpClient.execute(request, someCallback);
        }

        batchLatch.await();
        kafkaConsumer.commitAsync();
    }

以下是回调的示例代码:

public class SomeCallback {
    // ...
    @Override
    public void completed(final HttpResponse response) {
        // do something
        logger.info("{} - blablabla", status, ...);
        latch.countDown();
    }

    @Override
    public void failed(final Exception ex) {
        // do something
        logger.error("{} - blablabla", FAILED, ..., ex);
        latch.countDown();
    }

    @Override
    public void cancelled() {
        // do something
        logger.error("{} - blablabla!", CANCELLED, ...);
        latch.countDown();
    }
}

所以情况是,在某个时间点,我启动了程序,它开始使用来自kafka的数据。每次轮询的最大记录数为500。

由于Kafka上已有许多未消耗的数据,该程序面临着高吞吐量。

现在,日志看起来像这样:

[INFO ] 2018-04-29 04:11:29.234 [main] MyClass - Polling got records: 500
[INFO ] 2018-04-29 04:11:30.362 [I/O dispatcher 1] SUCCESS blablabla
[INFO ] 2018-04-29 xx:xx:xx.xxx [I/O dispatcher 2] SUCCESS blablabla
[INFO ] 2018-04-29 xx:xx:xx.xxx [I/O dispatcher 1] SUCCESS blablabla
[INFO ] 2018-04-29 xx:xx:xx.xxx [I/O dispatcher 1] SUCCESS blablabla
[INFO ] 2018-04-29 xx:xx:xx.xxx [I/O dispatcher 2] SUCCESS blablabla
...
...
[INFO ] 2018-04-29 06:28:35.003 [main] MyClass - Polling got records: 500
[INFO ] 2018-04-29 06:28:35.363 [I/O dispatcher 386] SUCCESS blablabla
[INFO ] 2018-04-29 xx:xx:xx.xxx [I/O dispatcher 385] SUCCESS blablabla
[INFO ] 2018-04-29 xx:xx:xx.xxx [I/O dispatcher 386] SUCCESS blablabla
[INFO ] 2018-04-29 xx:xx:xx.xxx [I/O dispatcher 385] SUCCESS blablabla
[INFO ] 2018-04-29 xx:xx:xx.xxx [I/O dispatcher 386] SUCCESS blablabla
...
[INFO ] 2018-04-29 06:31:35.003 [main] MyClass - Polling got records: 500
[INFO ] 2018-04-29 06:32:12.418 [I/O dispatcher 405] SUCCESS blablabla
[INFO ] 2018-04-29 xx:xx:xx.xxx [I/O dispatcher 406] SUCCESS blablabla
[INFO ] 2018-04-29 xx:xx:xx.xxx [I/O dispatcher 405] SUCCESS blablabla
[INFO ] 2018-04-29 xx:xx:xx.xxx [I/O dispatcher 406] SUCCESS blablabla
[INFO ] 2018-04-29 xx:xx:xx.xxx [I/O dispatcher 405] SUCCESS blablabla
...
[ERROR] 2018-04-29 xx:xx:xx.xxx [I/O dispatcher 405] FAILED blablabla! org.apache.http.ConnectionClosedException: Connection closed unexpectedly
[ERROR] 2018-04-29 xx:xx:xx.xxx [I/O dispatcher 406] FAILED blablabla! org.apache.http.ConnectionClosedException: Connection closed unexpectedly
// there the program stopped

这是我无法理解的:

  1. 为什么每500个请求(响应处理),只有两个I / O调度程序?是因为默认设置为max 2?
  2. 为什么每500个请求的I / O调度程序数量不断增加?通常,我之前经历过的是,I / O调度程序的数量会增加,但也会减少到1和2.我假设:它将重用一些以前的I / O调度程序,而不是每个创造新的时间。
  3. 为什么最后会出现ConnectionClosedException?是因为有太多的I / O调度员停止了这个程序吗?
  4. 更新

    感谢Oleg的评论,我发现不断增加的I / O调度程序数量是因为每次我从Kafka获取数据时,都会创建一个新的http客户端。然后,会有许多占用IO和资源的闲置客户端。这也是该计划停止的原因。

    我仍然有一些问题:

    1. 日志中显示的I / O调度程序的数量是什么意思?它是不同线程的数量吗?
    2. 如何控制一个http客户端的最大I / O调度程序数?它是由I / O调度员吗?
    3. 此I / O调度程序数与连接数之间有何区别?
    4. 如何根据我运行程序的机器和数据吞吐量/大小估算I / O调度程序的数量和连接数?

1 个答案:

答案 0 :(得分:2)

  1. 它代表一个帖子名称。

  2. 可以使用IOReactorConfig

  3. 控制I / O反应器属性和行为
  4. 少数I / O调度程序管理更多的连接。

  5. 对于绝大多数应用程序而言,每个CPU核心的一个I / O调度线程很可能是一个合理的默认值,而且不应该更改它。