HttpClient - 如何更快地判断服务器是否宕机?

5
我正在使用.NET的HttpClient发送请求到服务器。我将HttpClient.Timeout属性设置为10秒,因此当服务器无法在10秒内处理我的请求时,我会收到“任务已取消”的异常。直到这里都很好。
然而,如果服务器关闭,则需要大约20秒钟才能使HttpClient返回一个正确的异常,例如图片中的异常。我希望能够在10秒钟内看到此异常,以便区分服务器关闭和操作时间过长的情况。我在msdn文档中找不到任何相关信息。是否可以在HttpClient上设置超时?
以下是我如何构建HttpClient的方式:
 var webRequestHandler = new WebRequestHandler
        {
            UseProxy = false,
            Proxy = null,
            AllowPipelining = false,
            ContinueTimeout = TimeSpan.Zero,
            UseCookies = false,
            AllowAutoRedirect = false,
        };
 var httpClient = new HttpClient(webRequestHandler);
 httpClient.Timeout = timeout;

  httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "application/json");
  httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", userAgent);
  httpClient.DefaultRequestHeaders.ExpectContinue = false;

1
只是一个小比喻我想让你思考一下:如果你在和某人通电话并提出问题,是否有可靠(快速/即时)的方法来确定你所交谈的人是睡着了还是只是在认真思考? - MrPaulch
从逻辑上讲,你的问题并没有意义。你无法知道你没有收到响应是因为服务器宕机还是因为处理请求花费了太长时间,你只是没有收到响应。 - Ben Robinson
1
我认为从逻辑上讲这是有道理的,因为拥有HTTP响应和TCP连接之间存在差异。 - AlexDev
你可能无法可靠地检查你正在交谈的人是否已经倒下或思考,但是如果你有一个“如果我在10秒钟内没有得到答复就挂断”的规则,那么采取行动不应该需要20秒钟。 - vtortola
看一下ServicePointManager,有一些属性可能会对你有所帮助。另一个选择是使用HttpWebRequest,它具有响应开始的超时和数据到达的超时。 - AlexDev
2个回答

14

这个答案只是在@brz的例子上进行了扩展。

您可以使用此方法,该方法不会阻止线程(Task.Wait 会阻止线程

var timeout = Task.Delay(10000); // 10 seconds timeout
var request = httpClient.GetAsync("http://www.google.com");

await Task.WhenAny(timeout, request); // wait for either timeout or the request

if (timeout.IsCompleted) // if the timeout ended first, then handle it
{
    // handle timeout
}

// otherwise continue processing the request result
var response = await request;

4
根据msdn中提到的,使用超时无法处理这个问题:

域名系统(DNS)查询可能需要长达15秒才能返回或超时。如果您的请求包含需要解析的主机名,并将超时设置为小于15秒的值,则在WebException指示请求超时之前,可能需要15秒或更长时间。

然而,另一种方法是将您的请求包装在另一个任务中,并从那里处理超时:
var task = Task.Run(() => { 
                var req = new HttpClient().GetAsync("http://www.google.com");
                if (!req.Wait(10000))//wait for 10 seconds
                    throw new TaskCanceledException(req);
            });
task.Wait();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接