You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker容器中用HttpClient调用Microsoft Graph超时100秒,但curl可正常访问

问题:树莓派Docker容器中.NET 6调用Microsoft Graph超时,curl正常

我在树莓派的Docker容器中运行.NET 6/ASP.NET Core应用,通过Microsoft Graph SDK访问Outlook和OneDrive。7月29日周五,未改动运行环境的情况下应用突然无法正常工作,推测可能是Azure Active Directory或Graph的令牌行为等发生变更。

我剥离了应用中的Graph相关层排查问题:在容器内使用以下HttpClient代码调用Graph接口时,即使设置了Timeout.InfiniteTimeSpan,仍会在100秒后超时:

var client = new HttpClient();
client.Timeout = Timeout.InfiniteTimeSpan;
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token.AccessToken);
client.BaseAddress = new Uri("https://graph.microsoft.com");

var response = await client.GetAsync("v1.0/me");
var result = await response.Content.ReadAsStringAsync();

return Ok(new HealthResult { Result = result });

超时错误信息如下:

2022-07-31T07:46:21.622984734Z fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
2022-07-31T07:46:21.623189265Z       An unhandled exception has occurred while executing the request.
2022-07-31T07:46:21.623227911Z       System.Threading.Tasks.TaskCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
2022-07-31T07:46:21.623305047Z        ---> System.TimeoutException: A task was canceled.
2022-07-31T07:46:21.623336974Z        ---> System.Threading.Tasks.TaskCanceledException: A task was canceled.

但使用相同的访问令牌,通过以下调用curl的代码调用同一接口却能正常获取响应:

var process = new System.Diagnostics.Process();
process.StartInfo.FileName = "curl";
process.StartInfo.Arguments = $"-H \"Authorization: Bearer {token.AccessToken}\" https://graph.microsoft.com/v1.0/me";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.Start();

string consoleResult = process.StandardOutput.ReadToEnd();
return Ok(new HealthResult { Result = consoleResult });

正常响应示例:

{"result":"{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users/$entity\",\"displayName\":\"John Doe\",\"surname\":\"Doe\",\"givenName\":\"John\",\"id\":\"1234567890abcdef\",\"userPrincipalName\":\"john.doe@outlook.com\",\"businessPhones\":[],\"jobTitle\":null,\"mail\":null,\"mobilePhone\":null,\"officeLocation\":null,\"preferredLanguage\":null}"}

已尝试的排查操作:

  • 在GitHub Codespaces的devcontainer中运行应用,无异常;
  • 不带令牌调用Graph,仍出现curl正常、HttpClient超时的情况;
  • 设置Timeout.InfiniteTimeSpan后,需等待7-8分钟才能得到正确结果。

排查思路

  1. 检查Docker容器网络配置

    • 验证容器DNS解析是否正常,对比curl与HttpClient的DNS结果(可在容器内执行nslookup graph.microsoft.com测试);
    • 检查容器网络模式(如bridge/host)是否存在隐性变更,尝试切换网络模式复现测试;
    • 确认容器代理设置,curl可能默认继承系统代理,而HttpClient需显式配置。
  2. 排查.NET HttpClient底层行为差异

    • 强制HttpClient使用HTTP/1.1,禁用HTTP/2支持(ARM架构下.NET的HTTP/2实现可能存在兼容性问题):
      var handler = new SocketsHttpHandler { UseHttp2 = false };
      var client = new HttpClient(handler);
      
    • 避免每次请求创建新HttpClient实例,复用实例排查连接池耗尽问题;
    • 添加请求头Connection: Close,禁用HTTP持久连接测试。
  3. 验证系统级网络差异

    • 在树莓派宿主机直接运行.NET应用,排除Docker容器的隔离影响;
    • 对比容器内curl命令与.NET调用curl的网络日志,确认请求参数完全一致;
    • 检查树莓派系统时间同步状态,虽然curl正常,但令牌验证对时间敏感仍需确认。
  4. 抓包分析网络交互细节

    • 在容器内用tcpdump或Wireshark捕获HttpClient与curl的请求数据包,对比TCP握手、请求头、响应流程的差异;
    • 查看是否存在数据包丢失、握手超时或服务端响应异常的情况。

内容的提问来源于stack exchange,提问作者Kai Walter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:37:01