【问题标题】:Connection to Sesame Store blocked与芝麻商店的连接被阻止
【发布时间】:2015-09-29 13:37:04
【问题描述】:

我在使用 SPARQL 查询芝麻三联商店时遇到了问题。在我成功运行多个查询后,与三重存储的连接会阻塞。我已经能够在AbstractConnPool.getPoolEntryBlocking 第 306 行查明问题:apache-httpcomponents 库的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 查询)。我也尝试过重用连接,但我仍然得到相同的块。

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

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

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

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

NB2。下面是更完整的代码-sn-p:

        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);
                }
            }
        }

【问题讨论】:

    标签: apache-httpcomponents sesame


    【解决方案1】:

    发生这种情况的原因是您在完成后没有在TupleQueryResult 上调用result.close()

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

    [...] 在我们完成之后,对 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 的形式提供),通过使用新的 Java 7/8 功能(例如 AutoCloseable 和 lambda 表达式),其中的许多功能变得更加优雅。

    【讨论】:

    • 谢谢,这确实是解决方案。到目前为止,我们使用的是
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-30
    • 1970-01-01
    • 2019-09-04
    • 1970-01-01
    • 2019-07-16
    • 2018-06-13
    相关资源
    最近更新 更多