与芝麻商店的连接被屏蔽

时间:2015-09-29 13:37:04

标签: apache-httpcomponents sesame

我在使用SPARQL查询芝麻三重商店时遇到了问题。成功运行多个查询后,连接到三重存储块。我已经能够在AbstractConnPool.getPoolEntryBlocking第306行success = future.await(deadline);库的apache-httpcomponents找到问题。如果我理解正确,此方法会在超过最大连接数时阻止。最多为5个连接,实际上该池中打开的连接数为5。

我不明白为什么此时有5个开放连接。 当我在evaluate上调用TupleQuery方法时会出现问题。每次我用

打开一个新连接
connection = repository.getConnection();

我也关闭了它:

} finally {
            if(connection!=null){
                try {
                    connection.close();
                    nclosedconnections++;
                    System.out.println("Connections: "+nconnections+"  closed: "+nclosedconnections);
                } catch (RepositoryException e) {
                    throw new SearchException("Could not close the triple store as a search engine.",this,null,e);
                }
            }
        }

我已经检查过RepositoryConnection开放的频率以及它关闭的频率。当方法阻止时,RepositoryConnection已被打开6次并已按预期关闭了5次。

每个连接也只使用一次(即对于一个SPARQL查询)。我也试过重用连接,但后来我仍然得到同样的阻止。

你有什么想法,为什么会出错,以及我如何解决这个问题?

NB 即可。 Sesame存储库在tomcat上运行,并且通过HTTP建立连接,即存储库是HTTPRepository,由以下人员创建:

repository = new HTTPRepository(repositoryURL);
repository.initialize();

我还检查了服务器上的芝麻日志,但芝麻服务器没有收到任何请求。问题似乎是在没有请求发送的客户端。

NB2 即可。以下是更完整的代码段:

        RepositoryConnection connection = null;
        String sparql = "" +
                "SELECT * WHERE {\n" +
                "   OPTIONAL{ <"+result.getURI()+"> <" + DC.TITLE+ "> ?title. }"+
                "   OPTIONAL{ <"+result.getURI()+"> <" + RDFS.LABEL+ "> ?label. }"+
                "   OPTIONAL{ <"+result.getURI()+"> <" + SKOS.PREF_LABEL+ "> ?prefLabel. }"+
                "   OPTIONAL{ <"+result.getURI()+"> <" + SKOS.ALT_LABEL+ "> ?altLabel. }"+
                "   OPTIONAL{ <"+result.getURI()+"> <" + DC.DESCRIPTION+ "> ?description. }"+
                "   OPTIONAL{ <"+result.getURI()+"> <" + RDFS.COMMENT+ "> ?comment. }"+
                "}\n";
        try{
            connection = repository.getConnection();
            nconnections++;
            System.out.println("Connections: "+nconnections+"  closed: "+nclosedconnections);
            TupleQuery query = connection.prepareTupleQuery(QueryLanguage.SPARQL,sparql);
            query.setMaxExecutionTime(2);
            TupleQueryResult results = query.evaluate();
            while (results.hasNext()){
               ...
            }
        } catch (RepositoryException e) {
            throw new SearchException("Could not access the triple store as a search engine.",this,null,e);
        } catch (QueryEvaluationException e) {
            throw new SearchException("Could retrieve data from the triple store as the SPARQL query could not be evaluated. SPARQL:\n"+sparql,this,null,e);
        } catch (MalformedQueryException e) {
            throw new SearchException("Could retrieve data from the triple store as the SPARQL query was malformed. SPARQL:\n"+sparql,this,null,e);
        } finally {
            if(connection!=null){
                try {
                    connection.close();
                    nclosedconnections++;
                    System.out.println("Connections: "+nconnections+"  closed: "+nclosedconnections);
                } catch (RepositoryException e) {
                    throw new SearchException("Could not close the triple store as a search engine.",this,null,e);
                }
            }
        }

1 个答案:

答案 0 :(得分:2)

发生这种情况的原因是,在您完成此操作后,您不会在result.close()上调用TupleQueryResult

Sesame API要求您在完成查询结果和迭代后显式调用close()。引用the programmers' manual

  

[...]在完成TupleQueryResult之后,调用TupleQueryResult上的close()操作很重要。 TupleQueryResult延迟评估并保持资源(例如与底层数据库的连接)保持打开状态。关闭TupleQueryResult会释放这些资源。不要忘记迭代结果可能会导致异常!确保没有连接不必要地保持打开的最好方法是在finally子句中调用close()。

推荐的模式是使用try-finally块:

  TupleQueryResult result = tupleQuery.evaluate();
  try {
      while (result.hasNext()) {  
         // process result items
      }
  }
  finally {
      result.close();
  }

顺便说一下,在使用旧版Sesame时没有遇到此问题的原因是,有一个未记录的功能会在查询结果完全耗尽时自动关闭它。 在2.8版中,通过HTTP处理查询结果已完全重新实现,并且此未记录的功能不是它的一部分。因此,虽然不严格地说是一个错误(“官方”方式一直是你需要自己关闭它),但它是实践行为的回归。我已将此记录为一个问题(请参阅SES-2323),它将在下一个修补程序版本中修复。

顺便说一下,有几种方法可以使查询处理更容易一些,特别是如果您不特别需要对结果进行流处理。例如,您可以执行以下操作:

List<BindingSet> results = QueryResults.asList(query.evaluate());

将整个查询结果拉为简单List,并自动关闭基础QueryResult

此外:在即将发布的Sesame 4.0版本(目前可用作4.0.0-RC1)中,通过使用{J} {1}}和lambda-等新的Java 7/8功能,使其更加优雅。表达式。