Flask/App Engine应用无法连接Google Cloud MySQL问题求助
环境信息
- Python版本:3.8
- 依赖包:Flask-SQLAlchemy2.5.1、pymysql1.0.2
相关代码
mydatabase.py
unix_socket = "/cloudsql/{conn_name}".format(conn_name=DBCONNECTION) SQLALCHEMY_DATABASE_URI = ("mysql+pymysql://{user}:{password}@/{database}?unix_socket={socket}").format(user=USER, password=PWD,database=SQLDB, socket=unix_socket) db = SQLAlchemy()
main.py
from mydatabase import db,SQLALCHEMY_DATABASE_URI db.init_app(app)
报错信息
"POST /signin HTTP/1.1" 500
2022-12-06 14:41:34 default[2022120025] [2022-12-06 14:41:34,165] ERROR in app: Exception on /signin [POST]
2022-12-06 14:41:34 default[2022120025] Traceback (most recent call last): File "/layers/google.python.pip/pip/lib/python3.8/site-packages/pymysql/connections.py", line 602, in connect sock.connect(self.unix_socket) ConnectionRefusedError: [Errno 111] Connection refused
...
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")
已执行操作
- 为Compute Engine默认服务账号和App Engine默认服务账号添加Cloud SQL管理员权限
- 通过
curl api.ipify.org获取公网IP并加入Cloud SQL授权列表
排查步骤
1. 确认Cloud SQL实例连接名格式正确
Cloud SQL连接名格式为项目ID:区域:实例名,检查DBCONNECTION变量是否完全匹配,无拼写错误或多余空格。
2. 启用Cloud SQL Admin API
进入Google Cloud控制台,搜索「Cloud SQL Admin API」,确认API状态为「已启用」。未启用则点击启用,等待几分钟后重试连接。
3. 修正App Engine服务账号权限
确保App Engine默认服务账号(格式:项目ID@appspot.gserviceaccount.com)拥有Cloud SQL Client或Cloud SQL Editor权限(无需管理员权限),仅配置Compute Engine服务账号无效。
4. 添加App Engine部署配置的Cloud SQL引用
在app.yaml中添加实例连接名配置,否则App Engine无法挂载Unix套接字:
标准环境:
runtime: python38 env: standard beta_settings: cloud_sql_instances: "你的实例连接名"
灵活环境:
runtime: python env: flex beta_settings: cloud_sql_instances: "你的实例连接名"
5. 验证数据库用户有效性
确认USER对应的数据库账号密码正确,且拥有访问目标数据库的权限。可通过Cloud SQL控制台「用户」页面或本地客户端测试账号可用性。
6. 检查Unix套接字路径
添加调试代码打印unix_socket变量值,确认路径为/cloudsql/项目ID:区域:实例名,格式无误。
7. 移除公网IP授权干扰
Unix套接字连接不依赖IP白名单,可暂时移除之前添加的公网IP,避免混淆连接方式。
内容的提问来源于stack exchange,提问作者Nicolas-Fractal

