mcpField
G
google-app-engine

google-app-engine

github.com/jezweb云与 DevOps1.1k249 次安装3 周前更新
代码仓库

关于 google-app-engine

google-app-engine 是面向使用 Google App Engine 部署应用的开发者的实践指南,主要示例针对 Python 和 Django。内容涵盖标准与灵活环境、数据库和静态文件连接、扩缩容、密钥管理及常见故障排查。

主要功能

  1. 01标准与灵活环境配置
  2. 02Cloud SQL 连接示例
  3. 03静态文件托管方式
  4. 04Secret Manager 密钥管理
  5. 05扩缩容与多服务部署
  6. 06常见部署故障排查

适用场景

  1. 01配置 Django 应用并部署到 App Engine
  2. 02为 App Engine 应用连接 Cloud SQL
  3. 03为生产环境管理密钥和静态文件
  4. 04排查超时、内存或静态文件错误

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jezweb/claude-skills --skill google-app-engine

安装后在 Claude Code 中输入/google-app-engine确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

README.md
.claude-plugin/
plugin.json
references/
common-errors.md
rules/
google-app-engine.md
templates/
app-flex.yaml
app.yaml
requirements-gae.txt

详细介绍

Google App Engine

状态:生产就绪 最后更新:2026-01-24 依赖项:Google Cloud SDK(gcloud CLI) 技能版本:1.0.0


快速入门(10 分钟)

1. 先决条件
# Install Google Cloud SDK
# macOS
brew install google-cloud-sdk

# Or download from https://cloud.google.com/sdk/docs/install

# Authenticate
gcloud auth login
gcloud config set project YOUR_PROJECT_ID

# Enable required APIs
gcloud services enable appengine.googleapis.com
gcloud services enable sqladmin.googleapis.com
gcloud services enable secretmanager.googleapis.com
2. 创建 app.yaml
# app.yaml - Standard Environment (Python 3.12)
runtime: python312
instance_class: F2

env_variables:
  DJANGO_SETTINGS_MODULE: "myproject.settings.production"

handlers:
  # Static files (served directly by App Engine)
  - url: /static
    static_dir: staticfiles/
    secure: always

  # All other requests go to the app
  - url: /.*
    script: auto
    secure: always

automatic_scaling:
  min_instances: 0
  max_instances: 10
  target_cpu_utilization: 0.65
3. 部署
# Deploy to App Engine
gcloud app deploy

# Deploy with specific version
gcloud app deploy --version=v1 --no-promote

# View logs
gcloud app logs tail -s default

Standard 与 Flexible 环境

Standard 环境(大多数应用推荐)

适用场景:构建符合运行时限制的典型 Web 应用、API 或服务。

方面Standard
启动快(毫秒级)
扩缩容可缩至零
定价按请求付费
运行时Python 3.8-3.12
实例类型F1、F2、F4、F4_1G
最长请求时间60 秒
后台任务仅限 Cloud Tasks
# app.yaml - Standard
runtime: python312
instance_class: F2
Flexible 环境

适用场景:需要自定义运行时、Docker、更长的请求超时时间或后台线程。

方面Flexible
启动较慢(数分钟)
扩缩容至少 1 个实例
定价按 VM 小时计费
运行时任意(Docker)
最长请求时间60 分钟
后台任务原生线程
# app.yaml - Flexible
runtime: python
env: flex

runtime_config:
  runtime_version: "3.12"

resources:
  cpu: 1
  memory_gb: 0.5
  disk_size_gb: 10

automatic_scaling:
  min_num_instances: 1
  max_num_instances: 5

费用警告:Flexible 始终至少运行 1 个实例(最低约 $30-40/月)。


Cloud SQL 连接

Standard 环境(Unix 套接字)

App Engine Standard 通过 Unix 套接字而非 TCP/IP 连接 Cloud SQL。

# settings.py
import os

if os.getenv('GAE_APPLICATION'):
    # Production: Cloud SQL via Unix socket
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql',
            'NAME': os.environ['DB_NAME'],
            'USER': os.environ['DB_USER'],
            'PASSWORD': os.environ['DB_PASSWORD'],
            'HOST': f"/cloudsql/{os.environ['CLOUD_SQL_CONNECTION_NAME']}",
            'PORT': '',  # Empty for Unix socket
        }
    }
else:
    # Local development: Cloud SQL Proxy or local DB
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql',
            'NAME': os.environ.get('DB_NAME', 'localdb'),
            'USER': os.environ.get('DB_USER', 'postgres'),
            'PASSWORD': os.environ.get('DB_PASSWORD', ''),
            'HOST': '127.0.0.1',
            'PORT': '5432',
        }
    }
# app.yaml
env_variables:
  DB_NAME: "mydb"
  DB_USER: "myuser"
  CLOUD_SQL_CONNECTION_NAME: "project:region:instance"

# CRITICAL: Beta settings for Cloud SQL socket
beta_settings:
  cloud_sql_instances: "project:region:instance"

重要提示:beta_settings.cloud_sql_instances 用于启用 Unix 套接字。缺少此设置将导致连接失败。

使用 Cloud SQL Proxy 进行本地开发
# Download and run Cloud SQL Proxy
cloud-sql-proxy PROJECT:REGION:INSTANCE --port=5432

# Or use Docker
docker run -p 5432:5432 \
  gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.8.0 \
  PROJECT:REGION:INSTANCE

使用 Cloud Storage 托管静态文件

选项 1:App Engine 静态处理程序(简单)
# app.yaml
handlers:
  - url: /static
    static_dir: staticfiles/
    secure: always
    expiration: "1d"
# Collect static files before deploy
python manage.py collectstatic --noinput
gcloud app deploy

限制:文件会随部署一起打包,且单个文件大小不得超过 32MB。

选项 2:Cloud Storage(生产环境推荐)
# settings.py
from google.cloud import storage

GS_BUCKET_NAME = os.environ.get('GS_BUCKET_NAME')
STATICFILES_STORAGE = 'storages.backends.gcloud.GoogleCloudStorage'
DEFAULT_FILE_STORAGE = 'storages.backends.gcloud.GoogleCloudStorage'

# Or with django-storages
STORAGES = {
    "default": {
        "BACKEND": "storages.backends.gcloud.GoogleCloudStorage",
        "OPTIONS": {
            "bucket_name": GS_BUCKET_NAME,
            "location": "media",
        },
    },
    "staticfiles": {
        "BACKEND": "storages.backends.gcloud.GoogleCloudStorage",
        "OPTIONS": {
            "bucket_name": GS_BUCKET_NAME,
            "location": "static",
        },
    },
}
# Install django-storages
pip install django-storages[google]

# Create bucket with public access for static files
gsutil mb -l us-central1 gs://YOUR_BUCKET_NAME
gsutil iam ch allUsers:objectViewer gs://YOUR_BUCKET_NAME

环境变量和密钥

简单方案:app.yaml env_variables
# app.yaml - NOT for secrets!
env_variables:
  DJANGO_SETTINGS_MODULE: "myproject.settings.production"
  DEBUG: "False"

警告:app.yaml 会提交到源代码管理中。切勿在其中放置密钥。

生产环境:Secret Manager
# settings.py
from google.cloud import secretmanager

def get_secret(secret_id, version="latest"):
    """Fetch secret from Google Secret Manager."""
    client = secretmanager.SecretManagerServiceClient()
    project_id = os.environ.get('GOOGLE_CLOUD_PROJECT')
    name = f"projects/{project_id}/secrets/{secret_id}/versions/{version}"
    response = client.access_secret_version(request={"name": name})
    return response.payload.data.decode("UTF-8")

# Usage
if os.getenv('GAE_APPLICATION'):
    SECRET_KEY = get_secret('django-secret-key')
    DB_PASSWORD = get_secret('db-password')
# Create secrets
echo -n "your-secret-key" | gcloud secrets create django-secret-key --data-file=-
echo -n "db-password" | gcloud secrets create db-password --data-file=-

# Grant App Engine access
gcloud secrets add-iam-policy-binding django-secret-key \
    --member="serviceAccount:[email protected]" \
    --role="roles/secretmanager.secretAccessor"

扩缩容配置

自动扩缩容(默认)
automatic_scaling:
  min_instances: 0        # Scale to zero when idle
  max_instances: 10       # Cap maximum instances
  target_cpu_utilization: 0.65
  target_throughput_utilization: 0.6
  max_concurrent_requests: 80
  min_pending_latency: 30ms
  max_pending_latency: automatic
基本扩缩容(后台任务)
basic_scaling:
  max_instances: 5
  idle_timeout: 5m

适用场景:需要运行后台任务,且不希望立即缩容至零的服务。

手动扩缩容(固定实例)
manual_scaling:
  instances: 3

适用场景:工作负载可预测、需要 WebSocket 连接,或需要确保容量时。


实例类型

类型内存CPU每小时费用
F1256 MB600 MHz$0.05
F2512 MB1.2 GHz$0.10
F41 GB2.4 GHz$0.20
F4_1G2 GB2.4 GHz$0.30
# Recommended for Django
instance_class: F2  # 512MB usually sufficient

如果出现内存错误或响应缓慢,请升级到 F4。


预防已知问题

此技能可预防6 个已记录的问题:

问题 #1:Cloud SQL 连接被拒绝

错误:could not connect to server: Connection refused 原因:app.yaml 中缺少 beta_settings.cloud_sql_instances 预防措施:始终包含:

beta_settings:
  cloud_sql_instances: "project:region:instance"
问题 #2:静态文件返回 404

错误:部署后静态文件返回 404 原因:未运行 collectstatic,或处理程序顺序错误 预防措施:

python manage.py collectstatic --noinput

并确保静态处理程序位于兜底处理程序之前:

handlers:
  - url: /static
    static_dir: staticfiles/
  - url: /.*
    script: auto
问题 #3:502 Bad Gateway

错误:首次请求或负载较高时出现 502 错误 原因:冷启动超时,应用初始化耗时过长 预防措施:

  • 优化应用启动(延迟导入、连接池)
  • 使用 min_instances: 1 以避免冷启动
  • 增大 instance_class,以获得更多 CPU 和内存
问题 #4:超出内存限制

错误:日志中出现 Exceeded soft memory limit 原因:F1 类型(256MB)对 Django 及其依赖项来说内存不足 预防措施:Django 应用至少使用 instance_class: F2

问题 #5:请求超时

错误:60 秒后出现 DeadlineExceededError 发生原因:标准环境的请求时限为 60 秒 预防措施:

  • 将长时间运行的任务移至 Cloud Tasks
  • 使用 Flexible 环境以延长超时时间
  • 优化数据库查询
问题 #6:源代码管理中包含密钥

错误:Django SECRET_KEY 暴露在 git 历史记录中 发生原因:将密钥写入 app.yaml 的 env_variables 预防措施:使用 Secret Manager(参见环境变量部分)


部署命令

# Deploy default service
gcloud app deploy

# Deploy specific service
gcloud app deploy app.yaml --service=api

# Deploy without promoting (for testing)
gcloud app deploy --version=v2 --no-promote

# Split traffic between versions
gcloud app services set-traffic default --splits=v1=0.5,v2=0.5

# Promote version
gcloud app versions migrate v2

# View logs
gcloud app logs tail -s default

# Open app in browser
gcloud app browse

# List versions
gcloud app versions list

# Delete old versions
gcloud app versions delete v1 v2 --quiet

多服务架构

myproject/
├── app.yaml              # Default service
├── api/
│   └── app.yaml          # API service
├── worker/
│   └── app.yaml          # Background worker
└── dispatch.yaml         # URL routing
# dispatch.yaml
dispatch:
  - url: "*/api/*"
    service: api
  - url: "*/tasks/*"
    service: worker
# Deploy all services
gcloud app deploy app.yaml api/app.yaml worker/app.yaml dispatch.yaml

常见模式

健康检查端点
# urls.py
urlpatterns = [
    path('_ah/health', lambda r: HttpResponse('ok')),
    # ... other urls
]
# app.yaml
liveness_check:
  path: "/_ah/health"
  check_interval_sec: 30
  timeout_sec: 4
  failure_threshold: 2
  success_threshold: 2

readiness_check:
  path: "/_ah/health"
  check_interval_sec: 5
  timeout_sec: 4
  failure_threshold: 2
  success_threshold: 2
预热请求
# app.yaml
inbound_services:
  - warmup
# urls.py
urlpatterns = [
    path('_ah/warmup', warmup_view),
]

# views.py
def warmup_view(request):
    """Pre-warm caches and connections."""
    from django.db import connection
    connection.ensure_connection()
    return HttpResponse('ok')
HTTPS 重定向
# app.yaml
handlers:
  - url: /.*
    script: auto
    secure: always  # Redirects HTTP to HTTPS

本地开发

使用 Cloud SQL Proxy
# Terminal 1: Run Cloud SQL Proxy
cloud-sql-proxy PROJECT:REGION:INSTANCE --port=5432

# Terminal 2: Run Django
export DB_HOST=127.0.0.1
export DB_PORT=5432
python manage.py runserver
使用 dev_appserver(旧版)
# Not recommended - use Django's runserver instead
dev_appserver.py app.yaml
环境检测
# settings.py
import os

# Detect App Engine environment
IS_GAE = os.getenv('GAE_APPLICATION') is not None
IS_GAE_LOCAL = os.getenv('GAE_ENV') == 'localdev'

if IS_GAE:
    DEBUG = False
    ALLOWED_HOSTS = ['.appspot.com', '.your-domain.com']
else:
    DEBUG = True
    ALLOWED_HOSTS = ['localhost', '127.0.0.1']

捆绑资源

模板(templates/)
  • app.yaml - 标准环境配置
  • app-flex.yaml - Flexible 环境配置
  • requirements.txt - App Engine 的通用依赖项
参考资料(references/)
  • instance-classes.md - 实例类型详细对比
  • common-errors.md - 错误消息及解决方案

官方文档


依赖项

# requirements.txt
gunicorn>=21.0.0
google-cloud-secret-manager>=2.16.0
google-cloud-storage>=2.10.0
django-storages[google]>=1.14.0
psycopg2-binary>=2.9.9  # For PostgreSQL

生产环境检查清单

  • 在 Secret Manager 中配置 SECRET_KEY(而非 app.yaml)
  • 在生产环境设置中配置 DEBUG = False
  • 为你的域名配置 ALLOWED_HOSTS
  • 部署前运行 collectstatic
  • 设置 beta_settings.cloud_sql_instances
  • 实例类型适当(Django 使用 F2+)
  • 强制使用 HTTPS(secure: always)
  • 配置健康检查端点
  • 设置错误监控(Cloud Error Reporting)

最后验证日期:2026-01-24 | 技能版本:1.0.0

评论

支持 Markdown