异步请求超时通知

标签 timeout sparql dbpedia dotnetrdf

我正在将 SPARQL 查询作为异步请求发送到 SPARQL 端点,目前 DBpedia使用dotNetRDF library 。虽然简单的查询通常可以工作,但更复杂的查询有时会导致超时。

我正在寻找一种通过捕获发生时的某些事件来处理超时的方法。

我使用 one of the asynchronous QueryWithResultSet overloads 发送查询SparqlRemoteEndpoint class的.

SparqlResultsCallback所述,state 对象将被替换为 AsyncError instance如果异步请求失败。这确实表明存在超时,但似乎仅在发送请求后 10 分钟发生超时。当我的超时时间例如是30秒时,我想知道30秒后请求是否成功。 (35 秒也可以,但你明白了。)

这是一个发送两个请求的示例应用程序,第一个请求非常简单,很可能在超时(此处设置为 120 秒)内成功,而第二个请求则相当复杂,在 DBpedia 上很容易失败:

using System;
using System.Collections.Concurrent;

using VDS.RDF;
using VDS.RDF.Query;

public class TestTimeout
{
    private static string FormatResults(SparqlResultSet results, object state)
    {
        var result = new System.Text.StringBuilder();

        result.AppendLine(DateTime.Now.ToLongTimeString());

        var asyncError = state as AsyncError;
        if (asyncError != null) {
            result.AppendLine(asyncError.State.ToString());
            result.AppendLine(asyncError.Error.ToString());
        } else {
            result.AppendLine(state.ToString());
        }

        if (results == null) {
            result.AppendLine("results == null");
        } else {
            result.AppendLine("results.Count == " + results.Count.ToString());
        }

        return result.ToString();
    }

    public static void Main(string[] args)
    {
        Console.WriteLine("Launched ...");
        Console.WriteLine(DateTime.Now.ToLongTimeString());

        var output = new BlockingCollection<string>();

        var ep = new SparqlRemoteEndpoint(new Uri("http://dbpedia.org/sparql"));
        ep.Timeout = 120;

        Console.WriteLine("Server == " + ep.Uri.AbsoluteUri);
        Console.WriteLine("HTTP Method == " + ep.HttpMode);
        Console.WriteLine("Timeout == " + ep.Timeout.ToString());

        string query = "SELECT DISTINCT ?a\n"
            + "WHERE {\n"
            + "  ?a <http://www.w3.org/2000/01/rdf-schema#label> ?b.\n"
            + "}\n"
            + "LIMIT 10\n";

        ep.QueryWithResultSet(query,
            (results, state) => {
                output.Add(FormatResults(results, state));
            },
            "Query 1");

        query = "SELECT DISTINCT ?v5 ?v8\n"
            + "WHERE {\n"
            + "  {\n"
            + "    SELECT DISTINCT ?v5\n"
            + "    WHERE {\n"
            + "      ?v6 ?v5 ?v7.\n"
            + "      FILTER(regex(str(?v5), \"[/#]c[^/#]*$\", \"i\")).\n"
            + "    }\n"
            + "    OFFSET 0\n"
            + "    LIMIT 20\n"
            + "  }.\n"
            + "  OPTIONAL {\n"
            + "    ?v5 <http://www.w3.org/2000/01/rdf-schema#label> ?v8.\n"
            + "    FILTER(lang(?v8) = \"en\").\n"
            + "  }.\n"
            + "}\n"
            + "ORDER BY str(?v5)\n";

        ep.QueryWithResultSet(query,
            (results, state) => {
                output.Add(FormatResults(results, state));
            },
            "Query 2");

        Console.WriteLine("Queries sent.");
        Console.WriteLine(DateTime.Now.ToLongTimeString());
        Console.WriteLine();

        string result = output.Take();
        Console.WriteLine(result);

        result = output.Take();
        Console.WriteLine(result);

        Console.ReadLine();
    }
}

当我运行它时,我重复地得到如下输出:

13:13:23
Server == http://dbpedia.org/sparql
HTTP Method == GET
Timeout == 120
Queries sent.
13:13:25

13:13:25
Query 1
results.Count == 10

13:23:25
Query 2
VDS.RDF.Query.RdfQueryException: A HTTP error occurred while making an asynchron
ous query, see inner exception for details ---> System.Net.WebException: Der Rem
oteserver hat einen Fehler zurückgegeben: (504) Gatewaytimeout.
   bei System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
   bei VDS.RDF.Query.SparqlRemoteEndpoint.<>c__DisplayClass13.<QueryWithResultSe
t>b__11(IAsyncResult innerResult)
   --- Ende der internen Ausnahmestapelüberwachung ---
results == null

显然,确切的时间会有所不同,但关键是,基于第二个查询的错误消息是在请求发送后大约10分钟收到的,远低于设定的 2 分钟超时。

我在这里是否错误地使用了 dotNetRDF,或者我是否有意运行一个额外的计时器来自己测量超时并自行使用react,除非同时收到任何响应?

最佳答案

不,您没有错误地使用 dotNetRDF,而是似乎存在一个错误,即异步运行查询时,端点上设置的超时不会得到遵守。这已归档为 CORE-393

顺便说一句,即使修复了这个错误,您也不一定会在设置的超时时遇到硬超时。本质上是您为 SparqlRemoteEndpoint 实例的 Timeout 属性设置的值,该值用于设置 .Net Timeout 属性HttpWebRequestHttpWebRequest.Timeout 的文档声明如下:

Gets or sets the time-out value in milliseconds for the GetResponse and GetRequestStream methods.

因此,您可以等待超时时间来建立与 POST 查询的连接,然后再次等待超时时间来开始接收响应。一旦您开始接收响应,超时就变得无关紧要,并且处理响应的代码不会考虑超时。

因此,如果您想要一个硬超时,您最好自己实现它,从长远来看,这可能是我们可以添加到 dotNetRDF 中的东西,但实现起来更复杂,只需修复有关 HTTP 未兑现的超时的错误请求。

关于异步请求超时通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20996232/

相关文章:

sparql - 如何使用 DBpedia 知道字符串是人名还是地名?

c++ - 如何等待超时值

jquery - 如何将 SPARQL 查询的结果重用于另一个查询?

dbpedia - 如何使用DBPedia从内容中提取标签/关键字?

java - 尝试从 CONSTRUCT 查询异常中获取结果集

math - SPARQL 查询中的对数函数

freebase - 使用 freebase 进行命名实体识别

spring-boot - 在 Spring Boot 中为 LDAP 身份验证设置超时值

iphone - UIWebView 和超时

c# - 如何在 WebClient.DownloadFileAsync 上实现超时