Python 3.8 Django部署Google Cloud时第二个应用无法连接Cloud SQL实例的疑难求助
嘿,我之前帮同事排查过几乎一模一样的问题!核心原因肯定是你本地的GAE_APPLICATION环境变量被意外设置了,导致第二个应用启动时直接走了生产环境的数据库分支——而本地没有Cloud SQL的Unix Socket,连接失败后才 fallback 到了SQLite(或者你看到的SQLite是之前的残留数据)。下面给你一步步的排查和解决思路:
一、先确认环境变量是否真的存在
本地开发时GAE_APPLICATION这个变量本不该有值,先验证一下:
- Windows:打开命令提示符,输入
echo %GAE_APPLICATION%,如果输出了一串类似项目ID的内容,说明这个变量被全局或当前会话设置了; - Mac/Linux:终端输入
echo $GAE_APPLICATION,同理判断。
至于为什么第一个应用没问题?大概率是第一个应用启动时,你的终端会话里还没这个变量,而第二个应用启动时继承了之前的会话(比如你用同一个终端窗口操作了两个项目,中途执行过gcloud app相关命令,自动设置了这个变量)。
二、临时清除变量快速验证
如果确认变量存在,先临时清除它再启动第二个应用:
- Windows:输入
set GAE_APPLICATION=,回车后再启动Django; - Mac/Linux:输入
unset GAE_APPLICATION,再启动Django。
这时候应该会进入else分支,要么用SQLite,要么你可以修改else分支的配置,让本地通过代理连接Cloud SQL(毕竟用同一种数据库能避免很多本地和生产的差异)。
三、修改Settings逻辑,让环境判断更可靠
依赖GAE_APPLICATION的判断太容易误触发了,建议改成更健壮的方式:
方式1:用专门的本地开发标识变量
添加一个LOCAL_DEVELOPMENT变量,优先判断它,这样你能完全掌控环境切换:
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases import pymysql # noqa: 402 pymysql.version_info = (1, 4, 6, 'final', 0) # change mysqlclient version pymysql.install_as_MySQLdb() # 优先判断本地开发环境,可控性更强 if os.getenv('LOCAL_DEVELOPMENT', 'False').lower() == 'true': # 本地通过代理连接Cloud SQL的配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1', 'PORT': '3306', 'USER': 'admin', 'PASSWORD': '8t09q7OG0lx1jAy2', 'NAME': 'bscsportaltest', } } elif os.getenv('GAE_ENV') in ['standard', 'flex'] and os.getenv('GAE_APPLICATION'): # 生产环境:结合GAE_ENV判断,更准确 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '/cloudsql/someinstance:europe-west2:somename', 'PORT': '3306', 'USER': 'admin', 'PASSWORD': '8t09q7OG0lx1jAy2', 'NAME': 'bscsportaltest', } } else: # fallback到SQLite(可选保留) DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } }
本地启动时,只需要先设置变量:
- Windows:
set LOCAL_DEVELOPMENT=true && python manage.py runserver - Mac/Linux:
export LOCAL_DEVELOPMENT=true && python manage.py runserver
方式2:用GAE_ENV变量辅助判断
App Engine会自动设置GAE_ENV为standard或flex,结合这个变量判断生产环境,误触发的概率会低很多,就像上面代码里的那样。
四、检查gcloud CLI的影响
如果你在操作第二个应用前执行过gcloud app deploy或者gcloud app browse这类命令,gcloud CLI可能会自动在当前会话中设置GAE_APPLICATION变量。解决方法:
- 直接重启终端/命令提示符,清除会话中的临时环境变量;
- 用
gcloud config list确认当前项目是否是第二个应用的项目(不过这个其实不影响环境变量,但可以排除项目配置错误)。
五、验证代理连接的正确性
最后,确保你的Cloud SQL Proxy确实在监听第二个应用的数据库实例:
- 启动代理时,一定要用第二个项目的实例连接字符串:
Cloud_sql_proxy.exe -instances="second-project-id:europe-west2:second-db-name"=tcp:3306 - 可以用MySQL命令行或者客户端工具测试连接
127.0.0.1:3306,确认能正常访问第二个数据库,这样Django启动后也能正常连接。
内容的提问来源于stack exchange,提问作者Mark1982

