简体   繁体   English

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

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

I figured out the solution below.我想出了下面的解决方案。 I've left a second update for more clarification.我已经留下了第二次更新以进行更多说明。

Context语境

I've got a Discord bot, written in JavaScript using the discord.js library, that I've been working on by myself for nearly two years.我有一个 Discord 机器人,使用 discord.js 库在 JavaScript 中编写,我自己已经为此工作了将近两年。 I started using MySQL for database queries and such just over a year ago.一年多前,我开始使用 MySQL 进行数据库查询等。 This was on my local Windows 10 machine.这是在我本地的 Windows 10 机器上。 As this was a small hobby project at the time, I wasn't too worried about only having one MySQL instance for both development and production.由于当时这是一个业余爱好项目,我并不太担心只有一个 MySQL 实例用于开发和生产。 Finally, about 9 months ago, I was able to get the bot up and running on my Linode server, which runs Ubuntu 18.04, along with a copy of the MySQL database running there.终于,大约 9 个月前,我能够在我的 Linode 服务器上启动并运行该机器人,该服务器运行 Ubuntu 18.04,以及在那里运行的 MySQL 数据库的副本。

Up until now, with this setup, things have worked smoothly.到目前为止,有了这个设置,一切都进行得很顺利。 I use the local database on my Windows PC for development and testing, and then I push updates to the Ubuntu 18.04 server on Linode where the production database is.我在我的Windows PC上使用本地数据库进行开发和测试,然后我将更新推送到生产数据库所在的Linode上的Ubuntu 18.04服务器。 Also, just in case this helps, I do run the bot locally on my PC when doing development.此外,为了以防万一,我在进行开发时会在我的 PC 上本地运行该机器人。 There's two Discord bots with two unique tokens (one for production and one for development) so that I can keep the production one running while I work on updates.有两个 Discord 机器人,带有两个独特的令牌(一个用于生产,一个用于开发),这样我就可以在进行更新时保持生产运行。 I don't have the development bot running on the server 24/7 like the production bot.我没有像生产机器人那样在服务器上全天候 24/7 运行开发机器人。

Recently, however, a friend of mine (a self-proclaimed "for-loop extraordinaire") has started helping me with the development.然而,最近,我的一个朋友(自称“for-loop extraordinaire”)开始帮助我进行开发。 As such, we think now is a good time to have the development database active 24/7 as well, so that he may work on the bot whether I'm around or not.因此,我们认为现在也是让开发数据库 24/7 处于活动状态的好时机,这样无论我在不在,他都可以在机器人上工作。 This is where we get to the problem.这就是我们遇到问题的地方。

The Issue问题

I've left an update below as I've switched to the mysql2 package to try and find a solution.当我切换到mysql2 package 以尝试找到解决方案时,我在下面留下了更新。

So, in case it wasn't obvious, my goal here is very simple: I want my bot (when run locally on my, or my friend's, Windows machine using node.js) to connect to the remote database hosted on my Ubuntu 18.04 server, which is in the cloud , not my local.network.因此,如果不是很明显,我的目标非常简单:我希望我的机器人(当使用 node.js 在我或我朋友的 Windows 机器上本地运行时)连接到我的 Ubuntu 18.04 上托管的远程数据库服务器,它在云端,而不是我的 local.network。 I'm not afraid to admit that I'm far from a good web developer, so I don't know the logistics or the ins and outs of how this stuff really works.我不怕承认我远不是一个好的 web 开发人员,所以我不知道后勤或这些东西如何真正运作的来龙去脉。 It's a wonder I've made it this far.我能走到这一步真是奇迹。 But I thought it would be as simple as when connecting to a local MySQL instance.但我认为它会像连接到本地 MySQL 实例一样简单。 However, when I run the code, the console spits this error out at me.但是,当我运行代码时,控制台向我吐出这个错误。

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
}

Here's how my code is currently set up:这是我的代码当前的设置方式:

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!")
})

This method worked flawlessly when host was localhost (obviously) but when trying to connect remotely to the server on Linode, it just refuses.hostlocalhost (很明显)时,此方法可以完美运行,但当尝试远程连接到 Linode 上的服务器时,它只是拒绝。 I've tried both the Linode URL ( example.com ) as well as the IP ( LINODE.IP.ADDRESS.HERE ) address, both giving me the same error.我已经尝试了 Linode URL( example.com )和 IP( LINODE.IP.ADDRESS.HERE )地址,都给了我同样的错误。 Also I am aware that the mysql2 package for Node exists, I just haven't switched over yet.我也知道节点的mysql2 package 存在,我只是还没有切换。 If switching over would in fact help with this problem, please let me know.如果切换实际上有助于解决这个问题,请告诉我。

Solutions I've Tried我尝试过的解决方案

I've tried multiple answers from multiple similar questions on this site, such as this one and this , however none of the solutions work (including adding socketPath or changing port , etc.)我已经尝试从这个站点上的多个类似问题中获得多个答案,例如这个这个,但是没有一个解决方案有效(包括添加socketPath或更改port等)

I've tried changing the bind-address in the mysqld.cnf file to 0.0.0.0 and * , both of which did allow the bot to connect to the database, however access was still denied to actually read the database itself.我已经尝试将mysqld.cnf文件中的bind-address更改为0.0.0.0* ,这两者都允许机器人连接到数据库,但是仍然拒绝访问以实际读取数据库本身。 All I know is that it at least connected (though trying it again now has left me with an error message this time)我所知道的是它至少连接了(尽管现在再次尝试这一次给我留下了一条错误消息)

  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 is up to date so could this have to do with me not using mysql2 ? MySQL 是最新的所以这可能与我不使用mysql2有关吗? I'm not a fan of this option, regardless, but I thought I'd try it at least.无论如何,我不喜欢这个选项,但我想我至少会尝试一下。

My last resort was to create an SSH tunnel to connect to the database.我最后的办法是创建一个 SSH 隧道来连接到数据库。 Again, I'm still a web development novice, so I didn't fully know what I was doing, but I followed this guide here , but replacing the code I needed to, and ended up with a completely separate SSH connection error.同样,我仍然是 web 开发新手,所以我并不完全知道我在做什么,但我在这里遵循了本指南,但替换了我需要的代码,并以完全独立的 SSH 连接错误告终。 If SSH is absolutely required to accomplish what I want, then please let me know and I'll open a new question regarding that.如果绝对需要SSH 来完成我想要的,那么请告诉我,我将就此提出一个新问题。 I just wanted to mention it here to show that I have at least tried.我只是想在这里提一下,以表明我至少尝试过。

UPDATE更新

I've switched to using mysql2 , and while the error message is cleaner, it still persists.我已切换到使用mysql2 ,虽然错误消息更清晰,但它仍然存在。

I've attempted Archil's solution , and while it doesn't do much now that I've switched to mysql2 , it did provide me with a better understanding of MySQL's authentication system, which lead me to switch in the first place.我已经尝试过Archil 的解决方案,虽然它在我切换到mysql2后作用不大,但它确实让我更好地理解了 MySQL 的身份验证系统,这促使我首先切换。 Unfortunately, both Archil's answer and the mysql2 upgrade give me the same error:不幸的是,Archil 的回答和mysql2升级都给我同样的错误:

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

...despite the fact that I have granted 'root'@'%' all privileges. ...尽管我已授予'root'@'%'所有权限。

Regardless, again, this isn't my preferred way of doing this anyway.无论如何,无论如何,这不是我首选的方式。 If there's a more secure solution I'll gladly take it.如果有更安全的解决方案,我会很乐意接受。 I'll continue to try different solutions now that I have mysql2 installed.现在我已经安装了mysql2 ,我将继续尝试不同的解决方案。

UPDATE 2更新 2

After looking further into it, I figured out that permissions were NOT set up like I thought they were for the user I was trying to connect to the server with.在进一步研究之后,我发现权限并没有像我认为的那样为我试图连接到服务器的用户设置。 Once I fixed that, it did connect, but one of the tables that gets queried when the bot starts was showing as empty.一旦我修复了它,它确实连接了,但是当机器人启动时被查询的表之一显示为空。 Turns out it didn't exist!原来它不存在!

I had made a copy of the production database as a base for the new development one.我制作了一份生产数据库的副本作为新开发数据库的基础。 Problem was, it was missing a table that was on my local (old) development database.问题是,它缺少我本地(旧)开发数据库的一个表。 This lead to me believing that the bot was connecting with MySQL but not reading anything from the database.这让我相信该机器人正在与 MySQL 连接,但没有从数据库中读取任何内容。 I've added the correct table, and it works great, I've left a solution with more specific steps below.我添加了正确的表格,效果很好,我在下面留下了一个包含更具体步骤的解决方案。 in case this page is ever found by another novice web developer like me.以防其他像我这样的新手 web 开发人员找到此页面。 Thanks for the help!谢谢您的帮助!

I've left a second update as to how I got to this solution.关于如何获得此解决方案,我已经进行了第二次更新。

In short, setting the bind-address to 0.0.0.0 does work.简而言之,将bind-address设置为0.0.0.0确实有效。 If you're using the original mysql package, you'll need to follow Archil's solution .如果您使用的是原始mysql package,则需要遵循Archil 的解决方案 If you're using mysql2 and there's still an error (or if Archil's answer doesn't work with mysql ), make sure you double-check the permissions of the user you're trying to connect with using:如果您使用的是mysql2并且仍然存在错误(或者如果 Archil 的回答不适用于mysql ),请确保您仔细检查您尝试连接的用户的权限

SHOW GRANTS FOR 'user'@'%';

Assuming you're trying to connect remotely like I was, you'll need to create a user with the '%' wildcard if you haven't.假设您正在尝试像我一样进行远程连接,如果您还没有,则需要使用“%”通配符创建一个用户。

At this point it should connect, as it does for me, and if there's any errors after that, it's probably something to do with the tables within the database itself.此时它应该连接,就像它对我所做的那样,如果之后有任何错误,它可能与数据库本身内的表有关。

I've answer https://stackoverflow.com/a/50547109/4089212我已经回答https://stackoverflow.com/a/50547109/4089212

Check please.请检查。 You need to change auth mode for mySQL.您需要更改 mySQL 的授权模式。

In my case (mariadb) I've managed to change the bind address to 0.0.0.0 in the file:就我而言 (mariadb),我已经设法将文件中的绑定地址更改为 0.0.0.0:

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

After a restart I've managed to connect to the database:重新启动后,我设法连接到数据库:

service mysql restart

You may need to search for the correct file to edit in the folder /etc/mysql/mariadb.conf.d/您可能需要在文件夹/etc/mysql/mariadb.conf.d/中搜索要编辑的正确文件

Just look for bind-address (may have an IP address like 127.0.0.1)只需查找绑定地址(可能有 IP 地址,如 127.0.0.1)

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

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