Cloud Run部署Discord Bot连接Cloud SQL MySQL遇ETIMEDOUT问题
解决Cloud Run部署Discord Bot连接Cloud SQL MySQL的ETIMEDOUT问题
核心排查方向及解决方案
1. 确认Cloud Run与Cloud SQL的关联配置有效性
- 检查Cloud Run部署页面的「Cloud SQL connections」,确保已添加目标Cloud SQL实例,且两者处于同一区域(跨区域Unix Socket连接会直接超时)
- 验证环境变量
INSTANCE_UNIX_SOCKET的格式:必须严格为/cloudsql/[PROJECT_ID]:[REGION]:[INSTANCE_NAME],注意分隔符是冒号而非斜杠,这是最容易出错的点
2. 验证服务账号权限落地情况
- 确认Cloud Run的服务账号(格式为
[SERVICE_NAME]@[PROJECT_ID].iam.gserviceaccount.com)已被授予Cloud SQL Client或Cloud SQL Admin角色,且无IAM deny策略限制该账号的连接权限 - 无需在Cloud SQL实例的「用户」页面添加该服务账号,IAM角色已足够授权通过Auth Proxy连接
3. 修复代码的错误捕获与日志输出
本地能打印连接池但Cloud日志无输出,说明错误未被正确捕获或日志未上报,修改代码如下:
function createConnectionPoolCloud(){ const dboptions = { connectionLimit : 10, socketPath: process.env.INSTANCE_UNIX_SOCKET, user : process.env.DB_USER, password : process.env.DB_PASS, database : process.env.DB_NAME, waitForConnections: true, connectTimeout: 10000 // 延长超时时间便于排查 } const pool = mysql.createPool(dboptions); // 添加连接池错误监听 pool.on('error', (err) => { console.error('Connection pool error:', err.stack); }); return pool; }; // 调用时添加错误捕获 async function testPoolConnection() { try { const pool = createConnectionPoolCloud(); const promisePool = pool.promise(); const [rows] = await promisePool.query('SELECT 1 FROM DUAL'); console.log('Database connection successful:', rows); } catch (err) { console.error('Query execution failed:', err.stack); } } // 启动时执行测试 testPoolConnection();
修改后查看Cloud Logging,能获取更详细的错误栈信息,定位问题根源
4. 排查Dockerfile配置问题
- 使用官方Node.js镜像(如
node:18-slim)而非Alpine镜像,避免底层依赖缺失导致的连接异常 - 确认启动命令正确(如
CMD ["node", "index.js"]),确保服务正常启动后再尝试数据库连接 - 无需暴露端口(Discord Bot为主动出站服务),但需确保Cloud Run配置的端口与服务监听端口一致(若服务有HTTP接口)
5. 跳过连接池测试单连接
若连接池一直超时,先测试单连接排除连接池配置问题:
const mysql = require('mysql2'); async function testDirectConnection() { const connection = mysql.createConnection({ socketPath: process.env.INSTANCE_UNIX_SOCKET, user: process.env.DB_USER, password: process.env.DB_PASS, database: process.env.DB_NAME, connectTimeout: 10000 }); connection.connect((err) => { if (err) { console.error('Direct connection error:', err.stack); return; } console.log('Direct connection successful'); connection.query('SELECT 1 FROM DUAL', (err, rows) => { if (err) { console.error('Direct query error:', err.stack); } else { console.log('Direct query result:', rows); } connection.end(); }); }); } testDirectConnection();
- 若单连接成功:问题出在连接池配置(如
connectionLimit过高、waitForConnections逻辑冲突),可逐步调整连接池参数 - 若单连接也超时:问题在网络或权限层面,回到前两步重新排查
6. 确认Cloud SQL实例状态
- 检查Cloud SQL实例是否处于运行状态,无维护或暂停情况
- 确认
Cloud SQL Admin API已启用(在Google Cloud Console的API库中查看) - 无需配置Cloud SQL的公网IP白名单(Unix Socket通过Auth Proxy连接,不依赖公网IP防火墙)
内容的提问来源于stack exchange,提问作者Rishi Duggal
相关产品推荐
相关产品推荐

