我有一个螺栓正在为每个元组进行API调用(HTTP Get)。 为了避免需要等待响应,我当时希望使用apache HttpAsyncClient。
在bolt的prepare方法中实例化客户端后,execute方法从元组构造URL并调用sendAsyncGetRequest(url):
private void sendAsyncGetRequest(String url){
httpclient.execute(new HttpGet(url), new FutureCallback<HttpResponse>() {
@Override
public void completed(HttpResponse response) {
LOG.info("Response Code : " + response.getStatusLine());
LOG.debug(response.toString());
}
@Override
public void failed(Exception ex) {
LOG.warn("Async http request failed!", ex);
}
@Override
public void cancelled() {
LOG.warn("Async http request canceled!");
}
});
}
拓扑部署但Storm UI显示错误:
java.lang.RuntimeException: java.lang.IllegalStateException: Request cannot be executed; I/O reactor status: STOPPED at backtype.storm.utils.DisruptorQueue.consumeBatchToCursor(DisruptorQueue.java:12
答案 0 :(得分:0)
我没有遇到任何问题。 需要注意的关键事项是:
在bolt类范围
上声明客户端public class MyRichBolt extends BaseRichBolt {
private CloseableHttpAsyncClient httpclient;
在bolt的准备方法中实例化和统计客户端
@Override
public final void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
try {
// start the http client
httpclient = HttpAsyncClients.createDefault();
httpclient.start();
// other initialization code ...
} catch (Throwable exception) {
// handle errors
}
}
使用bolt的执行方法
进行调用@Override
public final void execute(Tuple tuple) {
// format the request url
String url = ...
sendAsyncGetRequest(url);
}
private void sendAsyncGetRequest(String url){
logger.debug("Async call to URL...");
HttpGet request = new HttpGet(url);
HttpAsyncRequestProducer producer = HttpAsyncMethods.create(request);
AsyncCharConsumer<HttpResponse> consumer = new AsyncCharConsumer<HttpResponse>() {
HttpResponse response;
@Override
protected void onResponseReceived(final HttpResponse response) {
this.response = response;
}
@Override
protected void onCharReceived(final CharBuffer buf, final IOControl ioctrl) throws IOException {
// Do something useful
}
@Override
protected void releaseResources() {
}
@Override
protected HttpResponse buildResult(final HttpContext context) {
return this.response;
}
};
httpclient.execute(producer, consumer, new FutureCallback<HttpResponse>() {
@Override
public void completed(HttpResponse response) {
// do something useful with the response
logger.debug(response.toString());
}
@Override
public void failed(Exception ex) {
logger.warn("!!! Async http request failed!", ex);
}
@Override
public void cancelled() {
logger.warn("Async http request canceled!");
}
});
}
答案 1 :(得分:0)
您是否在回调可以执行之前关闭主流中的客户端(client.close();)?
错误是说IO路径已经关闭。通常,异步客户端的实例应该重复用于重复请求,并且仅在已经进行“所有”请求时销毁,例如,在应用程序关闭时。