如何在未来取消时终止 Callable 中的 CXF Web 服务调用
题
编辑
这个问题现在已经经历了几次迭代,所以请随意浏览修订版本,以了解有关历史和尝试过的事情的一些背景信息。
我将 CompletionService 与 ExecutorService 和 Callable 一起使用,通过 CXF 生成的代码同时调用几个不同 Web 服务上的多个函数。这些服务都为我在项目中使用的一组信息提供不同的信息。然而,服务可能会在很长一段时间内无法响应而不抛出异常,从而延长了对组合信息集的等待时间。
为了解决这个问题,我同时运行所有服务调用,几分钟后想终止任何尚未完成的调用,最好从可调用内部或通过抛出来记录哪些尚未完成详细的异常。
这是一些高度简化的代码来说明我已经在做什么:
private Callable<List<Feature>> getXXXFeatures(final WiwsPortType port,
final String accessionCode) {
return new Callable<List<Feature>>() {
@Override
public List<Feature> call() throws Exception {
List<Feature> features = new ArrayList<Feature>();
//getXXXFeatures are methods of the WS Proxy
//that can take anywhere from second to never to return
for (RawFeature raw : port.getXXXFeatures(accessionCode)) {
Feature ft = convertFeature(raw);
features.add(ft);
}
if (Thread.currentThread().isInterrupted())
log.error("XXX was interrupted");
return features;
}
};
}
同时启动 WS 调用的代码:
WiwsPortType port = new Wiws().getWiws();
List<Future<List<Feature>>> ftList = new ArrayList<Future<List<Feature>>>();
//Counting wrapper around CompletionService,
//so I could implement ccs.hasRemaining()
CountingCompletionService<List<Feature>> ccs =
new CountingCompletionService<List<Feature>>(threadpool);
ftList.add(ccs.submit(getXXXFeatures(port, accessionCode)));
ftList.add(ccs.submit(getYYYFeatures(port accessionCode)));
ftList.add(ccs.submit(getZZZFeatures(port, accessionCode)));
List<Feature> allFeatures = new ArrayList<Feature>();
while (ccs.hasRemaining()) {
//Low for testing, eventually a little more lenient
Future<List<Feature>> polled = ccs.poll(5, TimeUnit.SECONDS);
if (polled != null)
allFeatures.addAll(polled.get());
else {
//Still jobs remaining, but unresponsive: Cancel them all
int jobsCanceled = 0;
for (Future<List<Feature>> job : ftList)
if (job.cancel(true))
jobsCanceled++;
log.error("Canceled {} feature jobs because they took too long",
jobsCanceled);
break;
}
}
我对这段代码遇到的问题是,在等待 port.getXXXFeatures(...) 返回时,Callables 实际上并没有被取消,而是以某种方式继续运行。正如你可以看到 if (Thread.currentThread().isInterrupted()) log.error("XXX was interrupted");
声明中断标志 是 在 port.getFeatures 返回后设置,只有在 Webservice 调用正常完成后才可用,而不是在我调用 Cancel 时被中断。
谁能告诉我我做错了什么以及如何在给定时间段后停止正在运行的 CXF Webservice 调用,并在我的应用程序中注册此信息?
最好的问候,蒂姆
解决方案
编辑3 新答案。
我看到这些选项:
- 将您的问题作为功能请求发布在 Apache CXF 上
- 自己修复 ACXF 并公开一些功能。
- 在 Apache CXF 中寻找异步 WS 调用支持的选项
- 考虑切换到不同的 WS 提供程序(JAX-WS?)
- 如果服务支持的话,您的 WS 是否使用 RESTful API 调用自己(例如带参数的纯 HTTP 请求)
仅限 uber 专家:使用真正的线程/线程组并使用非正统方法杀死线程。
其他提示
在CXF文档具有用于设定对HttpURLConnection的读超时一些指令: http://cwiki.apache.org/CXF20DOC/客户端的HTTP传输,包括-SSL-的support.html
这可能会满足您的需求。如果服务器没有及时响应,将引发异常和可调用会得到异常。 (除了存在这样的情况是可以替代挂的错误。我不记得,如果这是固定的2.2.2或者如果它只是在快照现在。)