与芝麻商店的连接被阻止
Connection to Sesame Store blocked
我 运行 在使用 SPARQL 查询芝麻三元组存储时遇到问题。在我成功 运行 几次查询后,与三元组存储块的连接。我已经能够在 AbstractConnPool.getPoolEntryBlocking
行 306: success = future.await(deadline);
apache-httpcomponents
库中查明问题所在。如果我理解正确,则此方法会在超过最大连接数时阻塞。最大值是 5 个连接,确实此时池中打开的连接数是 5。
我不明白的是为什么此时有 5 个打开的连接。
当我在 TupleQuery
上调用 evaluate
方法时出现问题。每次我用
打开一个新连接
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 查询)。我也试过重新使用连接,但我仍然得到相同的块。
你知道为什么会出错吗?我该如何解决这个问题?
注意。 tomcat 上的 Sesame 存储库 运行s 并且通过 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);
}
}
}
发生这种情况的原因是您在完成后没有在 TupleQueryResult
上调用 result.close()
。
Sesame API 要求您在完成查询结果和迭代后显式调用 close()
。引用自the programmers' manual:
[...] it is important to invoke the close() operation on the TupleQueryResult, after we are done with it. A TupleQueryResult evaluates lazily and keeps resources (such as connections to the underlying database) open. Closing the TupleQueryResult frees up these resources. Do not forget that iterating over a result may cause exceptions! The best way to make sure no connections are kept open unnecessarily is to invoke close() in the finally clause.
推荐的模式是使用 try-finally
块:
TupleQueryResult result = tupleQuery.evaluate();
try {
while (result.hasNext()) {
// process result items
}
}
finally {
result.close();
}
顺便说一下,使用旧版本的 Sesame 时没有出现此问题的原因是有一个未记录的功能,该功能会在查询结果完全耗尽时自动关闭它。
在 2.8 版中,通过 HTTP 处理查询结果被完全重新实现,这个未记录的特性不在其中。因此,虽然严格来说不是错误('official' 方式一直是您需要自己关闭它),但它是对实际行为的回归。我已将此记录为一个问题(参见 SES-2323),它将在下一个补丁版本中修复。
顺便说一句,有几种方法可以使查询处理更容易一些,特别是如果您不是特别需要对结果进行流式处理。例如,您可以这样做:
List<BindingSet> results = QueryResults.asList(query.evaluate());
将整个查询结果拉入一个简单的List
,并自动为您关闭底层QueryResult
。
此外:在即将发布的 Sesame 4.0 版本中(目前可作为 4.0.0-RC1 使用),通过使用新的 Java 7/8 功能,例如 AutoCloseable
和 lambda 表达式。
我 运行 在使用 SPARQL 查询芝麻三元组存储时遇到问题。在我成功 运行 几次查询后,与三元组存储块的连接。我已经能够在 AbstractConnPool.getPoolEntryBlocking
行 306: success = future.await(deadline);
apache-httpcomponents
库中查明问题所在。如果我理解正确,则此方法会在超过最大连接数时阻塞。最大值是 5 个连接,确实此时池中打开的连接数是 5。
我不明白的是为什么此时有 5 个打开的连接。
当我在 TupleQuery
上调用 evaluate
方法时出现问题。每次我用
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 查询)。我也试过重新使用连接,但我仍然得到相同的块。
你知道为什么会出错吗?我该如何解决这个问题?
注意。 tomcat 上的 Sesame 存储库 运行s 并且通过 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);
}
}
}
发生这种情况的原因是您在完成后没有在 TupleQueryResult
上调用 result.close()
。
Sesame API 要求您在完成查询结果和迭代后显式调用 close()
。引用自the programmers' manual:
[...] it is important to invoke the close() operation on the TupleQueryResult, after we are done with it. A TupleQueryResult evaluates lazily and keeps resources (such as connections to the underlying database) open. Closing the TupleQueryResult frees up these resources. Do not forget that iterating over a result may cause exceptions! The best way to make sure no connections are kept open unnecessarily is to invoke close() in the finally clause.
推荐的模式是使用 try-finally
块:
TupleQueryResult result = tupleQuery.evaluate();
try {
while (result.hasNext()) {
// process result items
}
}
finally {
result.close();
}
顺便说一下,使用旧版本的 Sesame 时没有出现此问题的原因是有一个未记录的功能,该功能会在查询结果完全耗尽时自动关闭它。 在 2.8 版中,通过 HTTP 处理查询结果被完全重新实现,这个未记录的特性不在其中。因此,虽然严格来说不是错误('official' 方式一直是您需要自己关闭它),但它是对实际行为的回归。我已将此记录为一个问题(参见 SES-2323),它将在下一个补丁版本中修复。
顺便说一句,有几种方法可以使查询处理更容易一些,特别是如果您不是特别需要对结果进行流式处理。例如,您可以这样做:
List<BindingSet> results = QueryResults.asList(query.evaluate());
将整个查询结果拉入一个简单的List
,并自动为您关闭底层QueryResult
。
此外:在即将发布的 Sesame 4.0 版本中(目前可作为 4.0.0-RC1 使用),通过使用新的 Java 7/8 功能,例如 AutoCloseable
和 lambda 表达式。