为什么来自 Google Secret Manager API 的 gRPC 调用在 Apache 运行时挂起?

Fer*_*mac 5 python apache django google-cloud-platform google-secret-manager

简而言之:

我有一个由 Apache 在 Google Compute Engine VM 上提供的 Django 应用程序。

我想在我的 Python 代码中访问来自 Google Secret Manager 的秘密(当 Django 应用程序初始化时)。

当我执行“python manage.py runserver”时,成功检索到秘密。但是,当我让 Apache 运行我的应用程序时,它会在向秘密管理器发送请求时挂起。

太多细节:

我遵循了这个问题的答案GCP VM Instance is not able to access Secrets from Secret Manager 尽管有适当的 Roles。我创建了一个服务帐户(不是默认帐户),并为其指定了“云平台”范围。我还在 Web 控制台中为其授予了“Secret Manager Admin”角色。

最初遇到麻烦后,我从 Web 控制台下载了服务帐户的 json 密钥,并将 GOOGLE_APPLICATION_CREDENTIALS env-var 设置为指向它。

当我直接在虚拟机上运行 django 服务器时,一切正常。当我让 Apache 运行应用程序时,我可以从日志中看到服务帐户凭据 json 已成功加载。

但是,当我通过 google.cloud.secretmanager.SecretManagerServiceClient.list_secret_versions 进行第一次 API 调用时,应用程序挂起。我的浏览器中甚至没有出现 500 错误,只有一个永恒的加载图标。我追踪执行情况如下:

grpc._channel._UnaryUnaryMultiCallable._blocking,第 926 行:'call = self._channel.segrelated_call(...'

它永远不会越过那条线。我无法弄清楚该调用去了哪里,因此我无法进一步检查它。

想法

我不太了解 GCP 服务帐户/API 访问。我无法理解为什么 django 开发服务器和 apache 之间会出现这种差异,因为它们都使用来自 json 的相同服务帐户凭据。我还感到惊讶的是,该应用程序只是挂在谷歌库中而不是抛出异常。发送请求时甚至有一个超时选项,但更改此选项没有任何区别。

我想知道这是否与我在自己的帐户下运行 django 服务器,但 apache 正在使用它使用的任何用户帐户这一事实有关?

更新

我尝试更改 apache 运行的用户/组以匹配我自己的用户/组。不用找了。

为 gRPC 本身启用了日志记录。当我使用 apache 和 django 开发服务器运行时,有明显的区别。

关于姜戈:

secure_channel_create.cc:178] grpc_secure_channel_create(creds=0x17cfda0,target=secretmanager.googleapis.com:443,args=0x7fe254620f20,保留=(nil))
init.cc:167] grpc_init(void)
client_channel.cc:1099] chand=0x2299b88: 为通道堆栈 0x2299b18 创建 client_channel
...
timer_manager.cc:188] 睡眠 1001 毫秒
...
client_channel.cc:1879] chand=0x2299b88 调用=0x229e440: 创建呼叫
...
call.cc:1980] grpc_call_start_batch(call=0x229daa0,ops=0x20cfe70,nops=6,tag=0x7fe25463c680,保留=(nil))
call.cc:1573] ops[0]: SEND_INITIAL_METADATA...
call.cc:1573] ops[1]: SEND_MESSAGE ptr=0x21f7a20
...

因此,创建了一个通道,然后创建了一个调用,然后我们看到 gRPC 开始执行该调用的操作(据我所知)。

在阿帕奇上:

secure_channel_create.cc:178] grpc_secure_channel_create(creds=0x7fd5bc850f70,target=secretmanager.googleapis.com:443,args=0x7fd583065c50,保留=(nil))
init.cc:167] grpc_init(void)
client_channel.cc:1099] chand=0x7fd5bca91bb8: 为通道堆栈 0x7fd5bca91b48 创建 client_channel
...
timer_manager.cc:188] 睡眠 1001 毫秒
...
timer_manager.cc:188] 睡眠 1001 毫秒
...

所以,我们创建了一个频道......然后就什么也没有了。没有通话,没有操作。因此,Python 代码坐在那里等待 gRPC 进行此调用,但它永远不会这样做。

Fer*_*mac 2

问题似乎是 Apache 的分叉行为以某种方式破坏了 gRPC。我无法确定确切的原因,但在我开始怀疑分叉是问题所在之后,我发现这个旧的 gRPC 问题表明分叉是一个有点棘手的领域。

我尝试重新配置 Apache 以使用不同的“多处理模块”,但由于我在这方面的经验有限,我无法让 gRPC 在其中任何一个下工作。

最后,我改用 nginx/uwsgi 而不是 Apache/mod_wsgi,并且没有遇到同样的问题。如果您正在尝试解决这样的问题并且必须使用 Apache,我建议您进一步研究 Apache 分叉、gRPC 如何处理分叉以及可用于 Apache 的不同 MPM。