簡體   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