System.Net.HttpClient:SendAsync失败,并带有OperationCanceledException,而没有通过网络的HTTP请求

时间:2018-12-10 17:54:54

标签: c# .net-core dotnet-httpclient

我们使用System.Net.Http.HttpClient进行k8s内部微服务之间的调用。

  • OS Linux(在docker内部)
  • dotnet TargetFramework:netcoreapp2.1
  • 服务器:红est
  • 协议:http

几天前,我们注意到http调用的行为非常奇怪: 微服务之间的一些呼叫(接近2-3%)失败并出现错误

System.OperationCanceledException: The operation was canceled.
   at System.Net.Http.HttpClient.HandleFinishSendAsyncError(Exception e, CancellationTokenSource cts)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at OurCode.HttpServiceClient.GetStringResponseAsync(String methodUri, HttpMethod httpMethod)
   ...another our code...

我们的http通话超时后(3秒)。但是在被叫服务内部没有有关呼叫的日志。

我们启用packetbeat来跟踪http请求,并且还注意到,没有执行任何从呼叫者服务到被呼叫者服务的http请求。 该服务的CPU,内存和网络一直都正常。

用于http调用的代码的简化版本如下:

public async Task<string> GetStringResponseAsync(String methodUri,  HttpMethod httpMethod)
{
    int timeoutInMilliseconds = 3000;
    var tokenSource = new CancellationTokenSource();
    var rm = new HttpRequestMessage(httpMethod, methodUri);
    Task<HttpResponseMessage> httpTask = HttpClient.SendAsync(rm, tokenSource.Token);
    tokenSource.CancelAfter(timeoutInMilliseconds);
    HttpResponseMessage response = await httpTask;
    await EnsureSuccessStatusCode(response);
    return await response.Content.ReadAsStringAsync();
}

任何关于没有网络请求http都会导致这种奇怪行为的问题的想法,我该怎么做进一步调查?

2 个答案:

答案 0 :(得分:2)

这只是意味着Web服务没有响应。

HttpClient会在超时时间过后抛出TaskCanceledException(从OperationCanceledException继承)。它不是直观的,对我(和其他人)没有任何意义,但是不幸的是,它就是这样做的。

对此here进行了一些讨论(一些人提到了一些变通方法,以区分超时与真正的取消,如果您愿意的话)。

答案 1 :(得分:0)

我不知道这对将来是否会有所帮助,但我遇到了同样的问题。原来,我托管的服务器默认情况下不会自动使用代理地址。我最终不得不在我的代码中添加以下内容:

using (var handler = new WinHttpHandler()){
       handler.WindowsProxyUsePolicy = WindowsProxyUsePolicy.UseCustomProxy;
       handler.Proxy = new WebProxy(server, port);
       //the rest of your code.....
}

此操作手动添加了代理服务器信息,我的控制台应用程序开始按预期运行。