繁体   English   中英

Node.js + MySQL:程序拒绝使用“ECONNREFUSED”连接到远程数据库

[英]Node.js + MySQL: Program refuses to connect to remote database with "ECONNREFUSED"

我想出了下面的解决方案。 我已经留下了第二次更新以进行更多说明。

语境

我有一个 Discord 机器人,使用 discord.js 库在 JavaScript 中编写,我自己已经为此工作了将近两年。 一年多前,我开始使用 MySQL 进行数据库查询等。 这是在我本地的 Windows 10 机器上。 由于当时这是一个业余爱好项目,我并不太担心只有一个 MySQL 实例用于开发和生产。 终于,大约 9 个月前,我能够在我的 Linode 服务器上启动并运行该机器人,该服务器运行 Ubuntu 18.04,以及在那里运行的 MySQL 数据库的副本。

到目前为止,有了这个设置,一切都进行得很顺利。 我在我的Windows PC上使用本地数据库进行开发和测试,然后我将更新推送到生产数据库所在的Linode上的Ubuntu 18.04服务器。 此外,为了以防万一,我在进行开发时会在我的 PC 上本地运行该机器人。 有两个 Discord 机器人,带有两个独特的令牌(一个用于生产,一个用于开发),这样我就可以在进行更新时保持生产运行。 我没有像生产机器人那样在服务器上全天候 24/7 运行开发机器人。

然而,最近,我的一个朋友(自称“for-loop extraordinaire”)开始帮助我进行开发。 因此,我们认为现在也是让开发数据库 24/7 处于活动状态的好时机,这样无论我在不在,他都可以在机器人上工作。 这就是我们遇到问题的地方。

问题

当我切换到mysql2 package 以尝试找到解决方案时,我在下面留下了更新。

因此,如果不是很明显,我的目标非常简单:我希望我的机器人(当使用 node.js 在我或我朋友的 Windows 机器上本地运行时)连接到我的 Ubuntu 18.04 上托管的远程数据库服务器,它在云端,而不是我的 local.network。 我不怕承认我远不是一个好的 web 开发人员,所以我不知道后勤或这些东西如何真正运作的来龙去脉。 我能走到这一步真是奇迹。 但我认为它会像连接到本地 MySQL 实例一样简单。 但是,当我运行代码时,控制台向我吐出这个错误。

Error: connect ECONNREFUSED LINODE.IP.ADDRESS.HERE:3306
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1141:16)
    --------------------
    at Protocol._enqueue (D:\Users\path\node_modules\mysql\lib\protocol\Protocol.js:144:48)
    at Protocol.handshake (D:\Users\path\node_modules\mysql\lib\protocol\Protocol.js:51:23)
    at Connection.connect (D:\Users\path\node_modules\mysql\lib\Connection.js:119:18)
    at Object.<anonymous> (D:\Users\path\bot\index.js:118:5)
    at Module._compile (internal/modules/cjs/loader.js:1138:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
    at Module.load (internal/modules/cjs/loader.js:986:32)
    at Function.Module._load (internal/modules/cjs/loader.js:879:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47 {
  errno: 'ECONNREFUSED',
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: 'LINODE.IP.ADDRESS.HERE',
  port: 3306,
  fatal: true
}

这是我的代码当前的设置方式:

const mysql = require("mysql")
//CONNECT TO MYSQL
var con = mysql.createConnection({
    host: 'example.com',
    port: 3306,
    user: 'user',
    password: 'pass',
    database: 'botDB',
    charset: "utf8mb4"
});

//CONNECTED TO DATABASE
con.connect(err => {
    if (err) { throw err };
    console.log("My database is up and running!")
})

hostlocalhost (很明显)时,此方法可以完美运行,但当尝试远程连接到 Linode 上的服务器时,它只是拒绝。 我已经尝试了 Linode URL( example.com )和 IP( LINODE.IP.ADDRESS.HERE )地址,都给了我同样的错误。 我也知道节点的mysql2 package 存在,我只是还没有切换。 如果切换实际上有助于解决这个问题,请告诉我。

我尝试过的解决方案

我已经尝试从这个站点上的多个类似问题中获得多个答案,例如这个这个,但是没有一个解决方案有效(包括添加socketPath或更改port等)

我已经尝试将mysqld.cnf文件中的bind-address更改为0.0.0.0* ,这两者都允许机器人连接到数据库,但是仍然拒绝访问以实际读取数据库本身。 我所知道的是它至少连接了(尽管现在再次尝试这一次给我留下了一条错误消息)

  code: 'ER_NOT_SUPPORTED_AUTH_MODE',
  errno: 1251,
  sqlMessage: 'Client does not support authentication protocol requested by server; consider upgrading MySQL client',
  sqlState: '08004',
  fatal: true

MySQL 是最新的所以这可能与我不使用mysql2有关吗? 无论如何,我不喜欢这个选项,但我想我至少会尝试一下。

我最后的办法是创建一个 SSH 隧道来连接到数据库。 同样,我仍然是 web 开发新手,所以我并不完全知道我在做什么,但我在这里遵循了本指南,但替换了我需要的代码,并以完全独立的 SSH 连接错误告终。 如果绝对需要SSH 来完成我想要的,那么请告诉我,我将就此提出一个新问题。 我只是想在这里提一下,以表明我至少尝试过。

更新

我已切换到使用mysql2 ,虽然错误消息更清晰,但它仍然存在。

我已经尝试过Archil 的解决方案,虽然它在我切换到mysql2后作用不大,但它确实让我更好地理解了 MySQL 的身份验证系统,这促使我首先切换。 不幸的是,Archil 的回答和mysql2升级都给我同样的错误:

{
  code: 'ER_ACCESS_DENIED_ERROR',
  errno: 1045,
  sqlState: '28000',
  sqlMessage: "Access denied for user 'root'@'MY.LOCAL.IP.ADDRESS' (using password: YES)"
}

...尽管我已授予'root'@'%'所有权限。

无论如何,无论如何,这不是我首选的方式。 如果有更安全的解决方案,我会很乐意接受。 现在我已经安装了mysql2 ,我将继续尝试不同的解决方案。

更新 2

在进一步研究之后,我发现权限并没有像我认为的那样为我试图连接到服务器的用户设置。 一旦我修复了它,它确实连接了,但是当机器人启动时被查询的表之一显示为空。 原来它不存在!

我制作了一份生产数据库的副本作为新开发数据库的基础。 问题是,它缺少我本地(旧)开发数据库的一个表。 这让我相信该机器人正在与 MySQL 连接,但没有从数据库中读取任何内容。 我添加了正确的表格,效果很好,我在下面留下了一个包含更具体步骤的解决方案。 以防其他像我这样的新手 web 开发人员找到此页面。 谢谢您的帮助!

关于如何获得此解决方案,我已经进行了第二次更新。

简而言之,将bind-address设置为0.0.0.0确实有效。 如果您使用的是原始mysql package,则需要遵循Archil 的解决方案 如果您使用的是mysql2并且仍然存在错误(或者如果 Archil 的回答不适用于mysql ),请确保您仔细检查您尝试连接的用户的权限

SHOW GRANTS FOR 'user'@'%';

假设您正在尝试像我一样进行远程连接,如果您还没有,则需要使用“%”通配符创建一个用户。

此时它应该连接,就像它对我所做的那样,如果之后有任何错误,它可能与数据库本身内的表有关。

我已经回答https://stackoverflow.com/a/50547109/4089212

请检查。 您需要更改 mySQL 的授权模式。

就我而言 (mariadb),我已经设法将文件中的绑定地址更改为 0.0.0.0:

sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf

重新启动后,我设法连接到数据库:

service mysql restart

您可能需要在文件夹/etc/mysql/mariadb.conf.d/中搜索要编辑的正确文件

只需查找绑定地址(可能有 IP 地址,如 127.0.0.1)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM