我在使用SPARQL查询芝麻三重商店时遇到了一个问题。在成功地运行了几个查询之后,连接到三重存储块。我已经能够在AbstractConnPool.getPoolEntryBlocking第306行:apache-httpcomponents库的success = future.await(deadline);中找到这个问题。如果正确理解,则当超过最大连接数时,此方法会阻塞。最大的连接是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);
}
}
}发布于 2015-10-01 23:03:46
发生这种情况的原因是,在完成result.close()操作之后,您不会在TupleQueryResult上调用它。
Sesame要求您在查询结果和迭代完成后显式调用close()。引用程序员手册
..。在完成TupleQueryResult的关闭()操作之后,调用它是非常重要的。TupleQueryResult延迟计算,并保持资源(例如对底层数据库的连接)处于打开状态。关闭TupleQueryResult可以释放这些资源。不要忘记,迭代结果可能会导致异常!确保没有不必要地保持连接打开的最佳方法是在finally子句中调用close()。
推荐的模式是使用try-finally块:
TupleQueryResult result = tupleQuery.evaluate();
try {
while (result.hasNext()) {
// process result items
}
}
finally {
result.close();
}顺便说一句,在使用旧版本的Sesame时,您没有这个问题的原因是,有一个没有文档的特性,当查询结果完全耗尽时,它会自动关闭查询结果。在第2.8版中,HTTP查询结果的处理被完全重新实现,而这个无文档化的特性并不是其中的一部分。因此,虽然不是严格地说是一个bug (官方的方式一直是你自己需要关闭它),但它是对实践行为的倒退。我已经将此记录为一个问题(请参阅SES-2323),它将在下一个补丁版本中修复。
顺便说一句,有几种方法可以使查询处理稍微容易一些,特别是当您不特别需要对结果进行流处理时。例如,您可以这样做:
List<BindingSet> results = QueryResults.asList(query.evaluate());它将整个查询结果提取到一个简单的List中,并自动为您关闭底层QueryResult。
还有:在即将发布的Sesame4.0版本(目前为4.0.0-RC1)中,通过使用新的Java7/8特性(如AutoCloseable和lambda-表达式),许多功能变得更加优雅。
https://stackoverflow.com/questions/32845465
复制相似问题