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

Docker容器中GoogleCredential.GetApplicationDefault无报错超时,如何排查?

问题描述

我在Compute Instance的Docker容器中运行.NET应用,尝试调用另一个Compute Instance。已将凭据文件credentials.json放在容器内,且设置了GOOGLE_APPLICATION_CREDENTIALS环境变量指向该文件。

执行代码时,在GoogleCredential.GetApplicationDefault()处超时,既无错误抛出,也没有任何超时原因提示。本地运行时曾遇到类似问题,通过反编译Google.Apis.Auth.OAuth2库并断点调试解决了凭据文件相关问题,但容器内无法这么做,没法诊断问题。

精简后的代码

public class TextToVectorService : ITextToVectorService
{
  private readonly string audience = "<DESTINATION_PRIVATE_CLOUDRUN_URL>";  // e.g. "https://text-to-vector-fs4g3759-ts.a.run.app"
  private readonly IMyLogger _logger;
  private readonly Lazy<Task<OidcToken>> _token;
  // ...

  public TextToVectorService(IMyLogger logger) {
    _logger = logger;
    _token = new Lazy<Task<OidcToken>>(async () => {
      try {
        _logger.LogMessage("Beginning token generation");
        var credential = GoogleCredential.GetApplicationDefault(); // <--- 超时位置

        _logger.LogMessage("Got credential");
        var tokenOptions = OidcTokenOptions.FromTargetAudience(audience)
                                           .WithTokenFormat(OidcTokenFormat.Standard);
        
        _logger.LogMessage($"Got credential type {credential.UnderlyingCredential.GetType().Name}");
        var oidcToken = await credential.GetOidcTokenAsync(tokenOptions).ConfigureAwait(false);
        
        return oidcToken;
      } catch (Exception e) {
        _logger.LogError(e);
        throw;
      }
    });
  }

  public async Task<IEnumerable<float>> EncodeText(string text)
  {
    _logger.LogMessage("Very start of Service call");
    // 设置API调用...

    try {
      _logger.LogMessage("Getting auth");
      var authHeader = await GenerateAuthHeader();
      
      _logger.LogMessage("Starting to make API call"); // 永远到不了这里
      // 发起API调用,返回结果...

    } catch (Exception e) {
        _logger.LogError(e);
        return Array.Empty<float>();
    }
  }

  private async Task<AuthenticationHeaderValue> GenerateAuthHeader()
  {
    var tokenValue = await _token.Value;
    var token = await tokenValue.GetAccessTokenAsync().ConfigureAwait(false); // 永远到不了这里
    _logger.LogMessage($"Got token: {token}");
    return new AuthenticationHeaderValue("bearer", token);
  }
}

日志输出

2023-04-19T14:08:16.441   message         Very start of Service call
2023-04-19T14:08:16.441   message         Getting auth
2023-04-19T14:08:16.441   message         Beginning token generation

没有其他日志输出,也没有抛出错误,随后请求超时。请问该如何获取更多问题相关信息?


排查方案

以下是几种能获取更多诊断信息的实用方法:

  • 启用Google客户端库详细日志
    在应用启动时添加配置,开启Google.Apis相关组件的调试日志,捕获凭据获取过程中的底层请求细节:

    using Google.Apis.Logging;
    // 应用初始化阶段添加
    var logger = new ConsoleLogger(LogLevel.Debug);
    Google.Apis.Logging.Logger.SetLogger(logger);
    

    也可以通过appsettings.json配置日志级别,将Google.Apis相关日志设为Debug或Trace,查看库内部的请求、重试等细节。

  • 手动加载凭据并添加前置检查
    不要依赖自动加载,改为手动读取凭据文件,同时添加文件存在性、权限检查的日志:

    var credPath = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS");
    _logger.LogMessage($"凭据文件路径:{credPath}");
    _logger.LogMessage($"文件是否存在:{File.Exists(credPath)}");
    if (File.Exists(credPath))
    {
        var fileInfo = new FileInfo(credPath);
        _logger.LogMessage($"文件权限:{fileInfo.GetAccessControl()}");
    }
    // 手动加载凭据
    var credential = GoogleCredential.FromFile(credPath);
    

    先确认容器能否正常读取凭据文件,排除路径或权限问题。

  • 添加超时控制强制触发异常
    给凭据获取操作加上超时包装,触发超时异常并捕获上下文:

    var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
    try
    {
        var credentialTask = Task.Run(() => GoogleCredential.GetApplicationDefault(), cts.Token);
        var credential = await credentialTask.WaitAsync(cts.Token).ConfigureAwait(false);
    }
    catch (OperationCanceledException ex)
    {
        _logger.LogError($"凭据获取超时:{ex.Message}\n堆栈信息:{ex.StackTrace}");
        throw;
    }
    
  • 容器内测试网络连通性
    进入运行中的Docker容器,测试关键端点的连通性:

    # 测试元数据服务(使用Compute Instance默认服务账号时需要)
    curl -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
    # 测试OAuth2令牌端点
    curl https://oauth2.googleapis.com/token
    

    若网络不通,说明容器存在网络配置问题,比如防火墙规则、VPC peering限制等。

  • 验证容器环境与文件挂载
    在容器内执行以下命令,确认环境变量和凭据文件状态:

    echo $GOOGLE_APPLICATION_CREDENTIALS
    cat $GOOGLE_APPLICATION_CREDENTIALS
    

    检查环境变量是否正确,文件内容是否完整无格式错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 09:38:09