【问题标题】:Aborting queries on neo4jrb中止对 neo4jrb 的查询
【发布时间】:2018-04-12 19:50:23
【问题描述】:

我正在按照以下方式运行:

results = queries.map do |query|
  begin
    Neo4j::Session.query(query)
  rescue Faraday::TimeoutError
    nil
  end
end

经过几次迭代后,我得到了一个未获救的Faraday::TimeoutError: too many connection resets (due to Net::ReadTimeout - Net::ReadTimeout),Neo4j 需要关闭再打开。

我相信这是因为查询本身没有中止 - 即连接超时但 Neo4j 继续尝试运行我的查询。我实际上想将它们超时,所以简单地增加超时窗口对我没有帮助。

我有一个侦察员,看起来我可以找到我的查询并通过 Neo4j API 中止它们,这将是我的下一步行动。

我的诊断正确吗?如果是这样,是否有推荐的方法来管理来自 neo4jrb 的查询(并中止它们)?

【问题讨论】:

    标签: ruby neo4j neo4j.rb


    【解决方案1】:

    Rebecca 关于手动管理查询是正确的。如果您希望 Neo4j 在特定时间段内自动停止查询,您可以在 neo4j conf 中进行设置:

    dbms.transaction.timeout=60s
    

    您可以在the docs 中找到有关该设置的更多信息。

    Ruby gem 使用 Faraday 通过 HTTP 连接到 Neo4j,Faraday 有一个内置的超时,它与 Neo4j 中的超时是分开的。我建议将 Neo4j 超时设置为比 Ruby 中的长一点(也许 5-10 秒)(here 是配置法拉第超时的文档)。如果它们都具有相同的超时,Neo4j 可能会在 Ruby 之前引发超时,从而导致不太明显的错误。

    【讨论】:

      【解决方案2】:

      查询管理可以通过 Cypher 完成。您必须是管理员用户。

      要列出所有查询,您可以使用CALL dbms.listQueries;

      要终止查询,您可以使用CALL dbms.killQuery('ID-OF-QUERY-TO-KILL');,其中 ID 是从查询列表中获取的。

      前面的语句必须作为原始查询执行;是否使用 OGM 无关紧要,只要您可以手动输入查询即可。如果无法手动输入查询,并且在您的框架中也无法这样做,那么您将不得不使用其他方法访问数据库才能执行查询。

      【讨论】:

        【解决方案3】:

        感谢 Brian 和 Rebecca 提供了有关 Neo4j 中查询管理的有用提示。这两种方法都为我的问题提供了可行的解决方案,Brian 明确列出了通过 Neo4jrb 实现解决方案的步骤,因此我将其标记为正确。

        正如两个答案所假设的,我所做的诊断是正确的 - 即,如果您从 Neo4jrb 运行查询并且 HTTP 连接超时,Neo4j 将继续执行查询,Neo4jrb 不会发出任何停止指令。

        Neo4jrb 不提供任何查询管理功能的包装器,因此简单地设置事务超时似乎是最明智的,并且可能我会采用。实际上拦截和终止查询也是可能的,但这意味着在一个线程上运行您的查询,以便您可以在另一个线程中查找它的 queryId。这是我正在使用 atm 的有点 hacky 的解决方案:

        class QueryRunner
          DEFAULT_TIMEOUT=70
        
          def self.query(query, timeout_limit=DEFAULT_TIMEOUT)
            new(query, timeout_limit).run
          end
        
          def initialize(query, timeout_limit)
            @query = query
            @timeout_limit = timeout_limit
          end
        
          def run
            start_time = Time.now.to_i
            Thread.new { @result = Neo4j::Session.query(@query) }
            sleep 0.5
        
            return @result if @result
        
            id = if query_ref = Neo4j::Session.query("CALL dbms.listQueries;").to_a.find {|x| x.query == @query }
              query_ref.queryId
            end
        
            while @result.nil?
              if (Time.now.to_i - start_time) > @timeout_limit
                puts "killing query #{id} due to timeout"
                Neo4j::Session.query("CALL dbms.killQuery('#{id}');")
                @result = []
              else
                sleep 1
              end
            end
            @result
          end
        end
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-14
          • 1970-01-01
          • 2019-03-02
          • 1970-01-01
          相关资源
          最近更新 更多