如何配置多URL指向同一Flex App Engine及多客户端Cloud SQL映射
Hey Johnny, let's break down your two questions step by step—here's how to tackle both scenarios:
1. 设置多个URL指向同一个Flex App Engine
让多个子域名(比如client1.app.mydomain.com)指向你的Flex应用,通过Google Cloud的自定义域名映射就能轻松实现:
- 验证根域名:打开Google Cloud控制台,进入你的App Engine项目,找到「自定义域名」页面。添加你的根域名(比如
mydomain.com),按照提示完成域名所有权验证——通常需要在域名服务商的DNS后台添加一条TXT或CNAME记录。 - 映射子域名到应用:根域名验证通过后,添加你需要的所有子域名(比如
client1.app.mydomain.com、client2.app.mydomain.com)。Google会为每个子域名提供对应的DNS记录(非根域名用CNAME, apex域名用A/AAAA记录),把这些记录添加到你的域名服务商DNS设置里即可。 - 开启HTTPS:App Engine会自动为自定义域名免费配置Let's Encrypt证书,记得为所有子域名开启HTTPS,保障客户端访问的安全性。
2. 多客户端通过各自Cloud SQL实例访问同一代码库
要让每个客户端连接到专属的Cloud SQL实例同时共用一套代码,你需要根据请求的子域名动态路由数据库连接。具体步骤如下:
步骤1:从子域名识别客户端
首先,你的Python应用需要从请求的子域名中提取客户端标识。这里给你两个常用框架的示例:
Flask示例
from flask import Flask, request, g app = Flask(__name__) @app.before_request def set_client_context(): # 提取客户端前缀(比如从"client1.app.mydomain.com"中拿到"client1") host_parts = request.host.split('.') g.client_id = host_parts[0] if len(host_parts) > 2 else None
Django示例
创建一个自定义中间件,把客户端ID绑定到请求对象上:
# your_app/middleware.py class ClientIdentificationMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): host_parts = request.get_host().split('.') request.client_id = host_parts[0] if len(host_parts) > 2 else None response = self.get_response(request) return response
然后在settings.py中注册这个中间件:
MIDDLEWARE = [ # ... 其他默认中间件 'your_app.middleware.ClientIdentificationMiddleware', ]
步骤2:动态连接对应的Cloud SQL实例
接下来,用识别到的客户端ID获取对应的Cloud SQL实例信息并建立连接,这里提供两种安全的实现方式:
方式1:用环境变量存储实例映射
在app.yaml中存储客户端ID到Cloud SQL实例连接名的映射:
env_variables: CLIENT_DB_MAP: '{"client1": "你的项目ID:地域:client1-sql", "client2": "你的项目ID:地域:client2-sql"}' DB_USER: "数据库用户名" DB_NAME: "数据库名"
然后在代码中动态加载连接(以PostgreSQL为例):
import json import os import psycopg2 def get_db_connection(client_id): # 加载客户端与实例的映射关系 db_map = json.loads(os.environ.get('CLIENT_DB_MAP', '{}')) instance_name = db_map.get(client_id) if not instance_name: raise ValueError(f"未为客户端 {client_id} 配置数据库") # 在Flex环境中连接Cloud SQL conn = psycopg2.connect( user=os.environ['DB_USER'], password=os.environ['DB_PASSWORD'], # 生产环境建议用Secret Manager存储密码! dbname=os.environ['DB_NAME'], host=f'/cloudsql/{instance_name}' ) return conn
方式2:用Secret Manager安全存储凭证
为了更高的安全性,把每个客户端的数据库凭证存在Google Cloud Secret Manager中:
- 为每个客户端创建一个Secret(比如
client1-db-creds),内容为JSON格式:{"instance_name": "你的项目ID:地域:client1-sql", "user": "数据库用户名", "password": "数据库密码", "db_name": "数据库名"} - 给你的App Engine服务账号授予
roles/secretmanager.secretAccessor权限 - 在代码中动态获取Secret并建立连接:
import json import os from google.cloud import secretmanager import psycopg2 def get_client_db_creds(client_id): client = secretmanager.SecretManagerServiceClient() secret_path = f"projects/{os.environ['GOOGLE_CLOUD_PROJECT']}/secrets/{client_id}-db-creds/versions/latest" response = client.access_secret_version(request={"name": secret_path}) return json.loads(response.payload.data.decode('utf-8')) def get_db_connection(client_id): creds = get_client_db_creds(client_id) conn = psycopg2.connect( user=creds['user'], password=creds['password'], dbname=creds['db_name'], host=f'/cloudsql/{creds["instance_name"]}' ) return conn
步骤3:配置Cloud SQL访问权限
- 给每个Cloud SQL实例的IAM权限列表中,添加你的App Engine服务账号,并授予
roles/cloudsql.client权限 - 如果用公网IP,需要把App Engine的出口IP段添加到Cloud SQL实例的授权网络中;如果用私有IP,需要配置App Flex环境与Cloud SQL实例所在VPC的对等连接
内容的提问来源于stack exchange,提问作者Mapperkids Lee
相关产品推荐
相关产品推荐

