2

编辑

到目前为止,这个问题已经经历了几次迭代,因此请随时查看修订版以查看有关历史和尝试的事情的一些背景信息。


我将 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 调用,并在我的应用程序中注册此信息?

最好的问候,蒂姆

4

2 回答 2

2

编辑 3新答案。

我看到这些选项:

  • 在 Apache CXF 上发布您的问题作为功能请求
  • 自己修复 ACXF 并公开一些功能。
  • 在 Apache CXF 中寻找异步 WS 调用支持的选项
  • 考虑切换到不同的 WS 提供程序(JAX-WS?)
  • 如果服务支持,您的 WS 是否使用 RESTful API 调用自己(例如带有参数的普通 HTTP 请求)
  • 仅限超级专家:使用真正的线程/线程组并使用非正统方法杀死线程。
于 2009-07-13T17:20:40.360 回答
1

CXF 文档有一些关于在 HTTPURLConnection 上设置读取超时的说明:http: //cwiki.apache.org/CXF20DOC/client-http-transport-including-ssl-support.html

那可能会满足您的需求。如果服务器没有及时响应,则会引发异常,并且可调用对象会收到异常。(除了有一个错误可能会挂起。我不记得它是针对 2.2.2 修复的,还是现在只是在 SNAPSHOTS 中。)

于 2009-07-15T03:32:25.210 回答