注意:我的整个应用程序部署在 Azure 上,并且位于同一虚拟网络 (vnet1) 中。我的应用程序是用 Go 构建的,并使用 gRPC 从客户端向服务器发出请求。我正在测试的整个流程在本地运行时有效。
我正在 Azure 上构建一个标准 Web 应用程序。我正在利用一个 Azure MySql 数据库、一个为我的后端服务部署映像的应用程序容器、另一个为我的前端服务部署映像的应用程序容器,以及一个允许公共访问我的前端的 API 网关,该网关与虚拟网络中的后端和数据库。
请求的生命周期因此可以被视为这样(对于任何不良的格式表示歉意):
*Within a virtual network
The API Gateway acts as the public access point*
----------------------------------------------------------------
| *within the same container app environment* |
| ---------------------------------------- |
user_browser -> | API Gateway -> | frontendContainer -> backendContainer | -> DB |
| ---------------------------------------- |
----------------------------------------------------------------
我确实有一个通配符私有 DNS 区域,以便我面向公众的 API 网关可以将请求路由到我的 vnet 包含的容器应用程序中。这会将
azurecontainerapps.io
映射到容器应用程序环境的静态 IP 地址,后端和前端容器都位于其中。这应该意味着 APIGateway->Frontend 和 Frontend->Backend 请求都应使用此 DNS 列表将基于容器的 FullQualifiedDomainName 的请求路由到容器应用程序环境,然后使用端口号路由到正确的容器/端点.
TLDR;为什么前端容器中的 gRPC 客户端无法成功与后端容器上的 gRPC 服务器建立 gRPC 连接/调用?
我的数据库已启动并正在运行。我可以通过公共接入点远程连接到它来验证这一点(我稍后会清理它)。 我的 backendContainer 也已启动并正在运行,容器上的日志显示它正在正确连接到数据库。 然而,frontendContainer 没有成功连接到后端容器,我不明白为什么。 API网关正在按预期工作,并且frontendContainer的网站已按预期公开可用。 frontendContainer 和 backendContainer 都位于同一个应用程序容器应用程序环境 (containerAppEnv1) 中,并且也位于同一个虚拟网络 (vnet1) 中。后端容器公开端口 8080。这反映在服务的 docker 文件以及后端容器的入口配置中:
az containerapp show --name {name} --resource-group {group_name} --query properties.configuration.ingress --output json
{
"additionalPortMappings": null,
"allowInsecure": true,
"clientCertificateMode": "Ignore",
"corsPolicy": null,
"customDomains": null,
"exposedPort": 0,
"external": true,
"fqdn": "{redacted}",
"ipSecurityRestrictions": null,
"stickySessions": {
"affinity": "none"
},
"targetPort": 8080,
"traffic": [
{
"latestRevision": true,
"weight": 100
}
],
"transport": "Http2"
}
前端服务器在启动时使用上面输出中给出的后端服务器的FullyQualifiedDomainName 启动与后端服务器的连接,代码如下:
// Set up a connection to the backend server.
conn, err := grpc.Dial(cfg.BackendURL, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("did not connect: %v", err)
}
onboardingClient = onboardingpb.NewOnboardingServiceClient(conn)
连接在创建时不会失败,但第一次尝试向客户端发出请求时,出现以下错误:
Error: {"message": "connection error: desc = "transport: Error while dialing: dial tcp {containerAppEnvironmentStaticIpAddress}:8080: i/o timeout""}
更新:似乎当我尝试阻止与后端建立的连接时,它失败并导致崩溃循环前端 Pod,当我尝试向前端发出请求时,Web 控制台上显示以下错误:
upstream connect error or disconnect/reset before headers. retried and the latest reset reason: connection termination
我已经在这个问题上绞尽脑汁了,不明白为什么前端服务无法成功向后端服务发出请求,尽管拥有 FQDN 并且位于同一个 VNet 上。我真的很感激任何人的帮助:)
我已验证:
后端容器正在运行
lis, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
server := grpc.NewServer()
onboardingpb.RegisterOnboardingServiceServer(server, s)