apache-httpcomponents - 与芝麻商店的连接被阻止

标签 apache-httpcomponents sesame

我在使用 SPARQL 查询芝麻三元组存储时遇到问题。在我成功运行多个查询后,与三重存储的连接被阻止。我已经能够在 apache-httpcomponentsAbstractConnPool.getPoolEntryBlocking 第 306 行:success = future.await(deadline); 查明问题> 图书馆。如果我理解正确的话,当超过最大连接数时,此方法会阻塞。最大连接数为 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 查询)。我也尝试过重用连接,但仍然得到相同的 block 。

您知道为什么会出错以及我该如何解决这个问题吗?

注意。 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);
                }
            }
        }

最佳答案

发生这种情况的原因是您在使用完 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 block :

  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)中,通过使用新的 Java 7/8 功能(例如 AutoCloseable),很多功能都变得更加优雅。和 lambda 表达式。

关于apache-httpcomponents - 与芝麻商店的连接被阻止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32845465/

相关文章:

java - Apache HttpComponents URIBuilder 具有多值参数

java - org.apache.http.ConnectionClosedException : Connection closed - PoolingNHttpClientConnectionManager

java - 我应该包括什么(使用 maven)以在我的 Java 应用程序中使用嵌入式芝麻存储库

scala - 比较模型的同一性,但与变量?用减号构造?

java - 在黑莓上使用 HttpCore

java - Hashicorp Vault - 无法识别的 SSL 消息,明文连接?

java - 使用 Http.Core 与 Http.Client 4 对话获取 ConnectionClosedException?

tomcat - 我如何找到 Sesame 存储库的位置?

java - FAIL - 上下文路径/openrdf-sesame 中的应用程序无法启动