无法从 App Engine 运行 连接到 Google Cloud SQL 中的 postgres Docker 具有自定义运行时的 .NET Core 应用程序
Unable to connect to postgres in Google Cloud SQL from App Engine running a .NET Core app in Docker with Custom runtime
我尝试了很多东西,但在尝试从我的 Google Cloud App Engine 连接到 Google Cloud PostgreSQL 实例时似乎无法通过 Exception while connecting
.
这可能是我作为开发人员处理过的最令人沮丧的事情。连接到数据库应该不难。
我做错了什么?
无效的事情:
- How to connect Google Cloud SQL via Google App engine Flex to botnet core app?
- https://cloud.google.com/sql/docs/postgres/connect-app-engine-flexible
- https://github.com/GoogleCloudPlatform/dotnet-docs-samples/tree/master/appengine/flexible/CloudSql
app.yaml:
runtime: custom
env: flex
beta_settings:
cloud_sql_instances: "<project-id>:<region>:<sql-instance>=tcp:5432"
最终使用的连接字符串:
Uid=<db_user>;Pwd=<db_password>;Host=cloudsql;Database=<db_name>
// other attempts:
Uid=<db_user>;Pwd=<db_password>;Host=cloudsql;Database=<db_name>;Port=5432
Uid=<db_user>;Pwd=<db_password>;Host=/cloudsql/<project-id>:<region>:<sql-instance>;Database=<db_name>
Uid=<db_user>;Pwd=<db_password>;Host='/cloudsql/<project-id>:<region>:<sql-instance>';Database=<db_name>
Uid=<db_user>;Pwd=<db_password>;Server='/cloudsql/<project-id>:<region>:<sql-instance>';Database=<db_name>
用法:
var connectionString = new NpgsqlConnectionStringBuilder(<connection string>)
{
SslMode = SslMode.Disable
};
NpgsqlConnection connection =
new NpgsqlConnection(connectionString.ConnectionString);
connection.Open();
相关堆栈跟踪:
Exception while connecting
at Npgsql.NpgsqlConnector.Connect(NpgsqlTimeout timeout)
at Npgsql.NpgsqlConnector.RawOpen(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
at Npgsql.NpgsqlConnector.Open(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
at Npgsql.ConnectorPool.AllocateLong(NpgsqlConnection conn, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
at Npgsql.NpgsqlConnection.<>c__DisplayClass32_0.<g__OpenLong|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Npgsql.NpgsqlConnection.Open()
Dockerfile(也许这很重要,因为我在我的 app.yaml
runtime
中使用了 custom
?):
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 8080
EXPOSE 443
ENV ASPNETCORE_URLS=http://*:8080
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
COPY . /src
WORKDIR /src
RUN dotnet restore --packages /packages
RUN dotnet publish -c Release -o /published
FROM base AS final
COPY --from=build /published /app/
WORKDIR /app
ENTRYPOINT [ "dotnet", "myapp.dll" ]
部署脚本:
gcloud beta app deploy --project <project-id>
编辑:
从云控制台检查我的 sql 实例的 PostgreSQL 错误,我在最终 Exception while connecting
错误之前看到以下错误:
System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (99): Cannot assign requested address /cloudsql/<my connection instance id>/.s.PGSQL.5432
您是否看过云 SQL here 的示例应用程序?
更新:
很难确定哪里出了问题,因为您提供了几个不同的选项,并且不清楚哪些组合导致了哪些错误。但是,基本上有 2 种不同的连接方式,重要的是您的代码与 app.yaml
:
中的配置相匹配
正在通过 TCP 端口连接
要通过 TCP 端口连接,请在 app.yaml
中使用以下内容:
beta_settings:
cloud_sql_instances: "<PROJECT_ID>:<REGION_ID>:<INSTANCE_ID>=tcp:5432"
然后为您的连接字符串使用以下格式:
"Host=172.17.0.1;Uid=<DB_USER>;Pwd=<DB_PASS>;Database=<DB_NAME>"
请注意,Host=172.17.0.1;
是部署到 Flex 时的 IP,但如果在本地使用云 SQL 代理,则为 127.0.0.1
。
通过 Unix 域套接字连接
要通过 Unix 套接字连接,请在 app.yaml
中使用以下内容:
beta_settings:
cloud_sql_instances: "<PROJECT_ID>:<REGION_ID>:<INSTANCE_ID>"
然后为您的连接字符串使用以下格式:
"Server=/cloudsql/<PROJECT_ID>:<REGION_ID>:<INSTANCE_ID>/.s.PGSQL.5432;Uid=<DB_USER>;Pwd=<DB_PASS>;Database=<DB_NAME>"
注意:您的驱动程序可能会自动添加 /.s.PGSQL.5432
- 有些会,有些不会。
疑难解答
如果您确定您的 app.yaml
和代码匹配正确但仍然收到超时消息,下一步将是检查您的应用程序日志。您可以使用 Stackdriver 并按 appengine.googleapis.com/cloud_sql_proxy
过滤以仅查看您的实例的日志。
一些常见的错误是:
- 实例没有publicIP(私网IP连接步骤不同)
- Cloud SQL Admin API 未在 App Engine 所在的项目中启用
- 使用的服务帐户(默认为
service-PROJECT_NUMBER@gae-api-prod.google.com.iam.gserviceaccount.com
)没有数据库所在项目的 Cloud SQL Client
IAM 角色或更高角色
我尝试了很多东西,但在尝试从我的 Google Cloud App Engine 连接到 Google Cloud PostgreSQL 实例时似乎无法通过 Exception while connecting
.
这可能是我作为开发人员处理过的最令人沮丧的事情。连接到数据库应该不难。
我做错了什么?
无效的事情:
- How to connect Google Cloud SQL via Google App engine Flex to botnet core app?
- https://cloud.google.com/sql/docs/postgres/connect-app-engine-flexible
- https://github.com/GoogleCloudPlatform/dotnet-docs-samples/tree/master/appengine/flexible/CloudSql
app.yaml:
runtime: custom
env: flex
beta_settings:
cloud_sql_instances: "<project-id>:<region>:<sql-instance>=tcp:5432"
最终使用的连接字符串:
Uid=<db_user>;Pwd=<db_password>;Host=cloudsql;Database=<db_name>
// other attempts:
Uid=<db_user>;Pwd=<db_password>;Host=cloudsql;Database=<db_name>;Port=5432
Uid=<db_user>;Pwd=<db_password>;Host=/cloudsql/<project-id>:<region>:<sql-instance>;Database=<db_name>
Uid=<db_user>;Pwd=<db_password>;Host='/cloudsql/<project-id>:<region>:<sql-instance>';Database=<db_name>
Uid=<db_user>;Pwd=<db_password>;Server='/cloudsql/<project-id>:<region>:<sql-instance>';Database=<db_name>
用法:
var connectionString = new NpgsqlConnectionStringBuilder(<connection string>)
{
SslMode = SslMode.Disable
};
NpgsqlConnection connection =
new NpgsqlConnection(connectionString.ConnectionString);
connection.Open();
相关堆栈跟踪:
Exception while connecting
at Npgsql.NpgsqlConnector.Connect(NpgsqlTimeout timeout)
at Npgsql.NpgsqlConnector.RawOpen(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
at Npgsql.NpgsqlConnector.Open(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
at Npgsql.ConnectorPool.AllocateLong(NpgsqlConnection conn, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
at Npgsql.NpgsqlConnection.<>c__DisplayClass32_0.<g__OpenLong|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Npgsql.NpgsqlConnection.Open()
Dockerfile(也许这很重要,因为我在我的 app.yaml
runtime
中使用了 custom
?):
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 8080
EXPOSE 443
ENV ASPNETCORE_URLS=http://*:8080
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
COPY . /src
WORKDIR /src
RUN dotnet restore --packages /packages
RUN dotnet publish -c Release -o /published
FROM base AS final
COPY --from=build /published /app/
WORKDIR /app
ENTRYPOINT [ "dotnet", "myapp.dll" ]
部署脚本:
gcloud beta app deploy --project <project-id>
编辑:
从云控制台检查我的 sql 实例的 PostgreSQL 错误,我在最终 Exception while connecting
错误之前看到以下错误:
System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (99): Cannot assign requested address /cloudsql/<my connection instance id>/.s.PGSQL.5432
您是否看过云 SQL here 的示例应用程序?
更新:
很难确定哪里出了问题,因为您提供了几个不同的选项,并且不清楚哪些组合导致了哪些错误。但是,基本上有 2 种不同的连接方式,重要的是您的代码与 app.yaml
:
正在通过 TCP 端口连接
要通过 TCP 端口连接,请在 app.yaml
中使用以下内容:
beta_settings:
cloud_sql_instances: "<PROJECT_ID>:<REGION_ID>:<INSTANCE_ID>=tcp:5432"
然后为您的连接字符串使用以下格式:
"Host=172.17.0.1;Uid=<DB_USER>;Pwd=<DB_PASS>;Database=<DB_NAME>"
请注意,Host=172.17.0.1;
是部署到 Flex 时的 IP,但如果在本地使用云 SQL 代理,则为 127.0.0.1
。
通过 Unix 域套接字连接
要通过 Unix 套接字连接,请在 app.yaml
中使用以下内容:
beta_settings:
cloud_sql_instances: "<PROJECT_ID>:<REGION_ID>:<INSTANCE_ID>"
然后为您的连接字符串使用以下格式:
"Server=/cloudsql/<PROJECT_ID>:<REGION_ID>:<INSTANCE_ID>/.s.PGSQL.5432;Uid=<DB_USER>;Pwd=<DB_PASS>;Database=<DB_NAME>"
注意:您的驱动程序可能会自动添加 /.s.PGSQL.5432
- 有些会,有些不会。
疑难解答
如果您确定您的 app.yaml
和代码匹配正确但仍然收到超时消息,下一步将是检查您的应用程序日志。您可以使用 Stackdriver 并按 appengine.googleapis.com/cloud_sql_proxy
过滤以仅查看您的实例的日志。
一些常见的错误是:
- 实例没有publicIP(私网IP连接步骤不同)
- Cloud SQL Admin API 未在 App Engine 所在的项目中启用
- 使用的服务帐户(默认为
service-PROJECT_NUMBER@gae-api-prod.google.com.iam.gserviceaccount.com
)没有数据库所在项目的Cloud SQL Client
IAM 角色或更高角色