ETIMEOUT错误 | 使用NodeJS连接Google Cloud SQL数据库

5

我已经在Google Cloud上创建了一个MySQL数据库,希望从另一个运行在Google Cloud上的节点Web应用程序中访问它。首先我在本地计算机上测试连接,当我在本地运行以下代码时,可以成功建立与我的数据库的连接并查看其中的数据。

'use strict';

// [START app]
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const app = express();
const mysql      = require('mysql');

var connection = mysql.createConnection({
  host     : 'Cloud SQL IP',
  user      : 'username',
  password  : 'password',
  database  : 'db_name'
});



// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())

// Make globals.js accessible
app.use(express.static(__dirname + '/'));


app.get('/', (req, res) => {
    connection.connect();

    connection.query('SELECT * FROM Users', function (error, results, fields) {
        if (error) throw error;
        console.log(results);
    });

    connection.end();
    res.status(200).send('Hello World!');
});

app.get('/login', (req, res) => {
    res.status(200).send();
});

// [START server]
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
  console.log(`App listening on port ${PORT}`);
  console.log('Press Ctrl+C to quit.');
});
// [END app]

然而,当我在我的Google应用引擎上运行相同的代码(无论是在端口8080上进行调试还是完全部署在https://myapp.appspot.com上),我会收到以下超时错误:
{ Error: connect ETIMEDOUT
    at Connection._handleConnectTimeout         (/home/megan_cooper2900/project/node_modules/mysql/lib/Connection.js:419:13)
at Socket.g (events.js:292:16)
at emitNone (events.js:86:13)
at Socket.emit (events.js:185:7)
at Socket._onTimeout (net.js:338:8)
at ontimeout (timers.js:386:14)
at tryOnTimeout (timers.js:250:5)
at Timer.listOnTimeout (timers.js:214:5)
--------------------
at Protocol._enqueue (/home/megan_cooper2900/project/node_modules/mysql/lib/protocol/Protocol.js:145:48)
at Protocol.handshake (/home/megan_cooper2900/project/node_modules/mysql/lib/protocol/Protocol.js:52:23)
at Connection.connect (/home/megan_cooper2900/project/node_modules/mysql/lib/Connection.js:130:18)
at app.get (/home/megan_cooper2900/journeyma/app.js:31:13)
at Layer.handle [as handle_request] (/home/megan_cooper2900/project/node_modules/express/lib/router/layer.js:95:5)
at next (/home/megan_cooper2900/project/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/home/megan_cooper2900/project/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/home/megan_cooper2900/project/node_modules/express/lib/router/layer.js:95:5)
at     /home/megan_cooper2900/project/node_modules/express/lib/router/index.js:281:22
    at Function.process_params         (/home/megan_cooper2900/project/node_modules/express/lib/router/index.js:335:12)
  errorno: 'ETIMEDOUT',
  code: 'ETIMEDOUT',
  syscall: 'connect',
  fatal: true }

为什么这个在Google App Engine应用程序上无法运行?

在主机属性中添加您的实例连接名称。 - Fran
主机值通常不是一个URL格式吗? - Megan
请查看有关从NodeJS连接的许多现有问题。简而言之,您需要使用App Engine中的连接支持,而不是通过IP连接。例如:https://dev59.com/7qXja4cB1Zd3GeqPZPUt。该问题涉及postgres,但解决方案相同。 - Vadim
@Megan 我也有同样的问题,但是我不能用上面的解决方案解决,你有其他的解决方法吗?谢谢。 - Smaillns
@Smaillns 抱歉,我没有其他的解决方案,因为原来的解决方案对我有效。 - Megan
2个回答

12

在您的mysql连接配置中,host 在App Engine上不起作用。您必须使用socketPath。socketPath是连接到unix域套接字的路径。当使用时,主机和端口会被忽略。(从在App Engine flex上使用Loopback转移知识。它让我头痛了好几天 lol)它的值是您的Cloud SQL实例连接名称。

所以在您的情况下,它应该看起来像这样:/cloudsql/my-project-12345:us-central1:mydatabase

var connection = mysql.createConnection({
  socketPath     : '/cloudsql/my-project-12345:us-central1:mydatabase',
  user      : 'username',
  password  : 'password',
  database  : 'db_name'
});

如果您在GCloud上使用Postgres,则这个过程类似,具体答案在这里


2
老兄,非常感谢。6个小时的痛苦。这不是一个愉快的星期天度过的方式。 - pyetti
我仍然有同样的问题,我该怎么办! - Smaillns
2
为了使其正常工作,您还需要在IAM表中为“App Engine默认服务帐户”添加“Cloud SQL客户端”角色。 - Klesun
设置socketPath并为应用引擎添加SQL客户端角色,结束了这几个小时的噩梦,谢谢。 - tiddlesticks
2
很小的事情,但是它是'/cloudsql/my-project-12345:us-central1:instance-name而不是套接字路径的数据库。 - smoore4

0

我也遇到了同样的问题,我在使用 Kubernetes pods 访问我的 CloudSQL 实例。通过在配置中增加超时时间,我得到了一个解决方案。

cloudSqlConfig: {
    connectionLimit: 10,
    host: 'your-host-ip',
    user: process.env.DB_USERNAME,
    password: process.env.DB_PASSKEY,
    database: 'myDB',
    connectTimeout: 20000,
    waitForConnections: true,
    queueLimit: 0
},

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接