淺談express 連接在線數(shù)據(jù)庫(kù)踩坑
1. 前言
在學(xué)習(xí) Node.js 開發(fā)的過程中,Express 框架無疑是最受歡迎的選擇之一。
作為一名前端開發(fā)者,我決定深入學(xué)習(xí)后端技術(shù),搭建一個(gè)完整的博客系統(tǒng)。
第一步自然是連接數(shù)據(jù)庫(kù),而我選擇了連接遠(yuǎn)程服務(wù)器上的 MySQL 數(shù)據(jù)庫(kù),而不是在本地搭建環(huán)境。
這看似簡(jiǎn)單的一步,卻讓我遇到了各種各樣的問題。
本文將記錄我在連接遠(yuǎn)程 MySQL 數(shù)據(jù)庫(kù)過程中遇到的各種坑,希望能幫助到同樣遇到困難的開發(fā)者。
2. 如何連接
2.1 環(huán)境準(zhǔn)備
首先,我們需要安裝必要的依賴:
npm install express mysql2 sequelize dotenv
2.2 配置文件
為了安全管理數(shù)據(jù)庫(kù)連接信息,我創(chuàng)建了 .env
文件來存儲(chǔ)敏感信息:
數(shù)據(jù)庫(kù)配置
DB_HOST=your_server_ip DB_PORT=3306 DB_NAME=your_database_name DB_USER=your_username DB_PASSWORD=your_password
服務(wù)器配置
PORT=3000 NODE_ENV=development
2.3 數(shù)據(jù)庫(kù)連接配置
然后創(chuàng)建 config/database.js
文件:
const { Sequelize } = require('sequelize'); require('dotenv').config(); // 從環(huán)境變量獲取數(shù)據(jù)庫(kù)配置 const DB_HOST = process.env.DB_HOST || 'localhost'; const DB_PORT = process.env.DB_PORT || 3306; const DB_NAME = process.env.DB_NAME || 'test_db'; const DB_USER = process.env.DB_USER || 'root'; const DB_PASSWORD = process.env.DB_PASSWORD || ''; // 創(chuàng)建 Sequelize 實(shí)例,連接到遠(yuǎn)程數(shù)據(jù)庫(kù) const sequelize = new Sequelize( DB_NAME, DB_USER, DB_PASSWORD, { host: DB_HOST, port: DB_PORT, dialect: 'mysql', pool: { max: 5, min: 0, acquire: 30000, idle: 10000 }, dialectOptions: { timezone: '+08:00' }, logging: process.env.NODE_ENV !== 'production' ? console.log : false } ); // 測(cè)試數(shù)據(jù)庫(kù)連接 const testConnection = async () => { try { await sequelize.authenticate(); console.log('數(shù)據(jù)庫(kù)連接成功!'); } catch (error) { console.error('無法連接到數(shù)據(jù)庫(kù):', error); } }; module.exports = { sequelize, testConnection };
2.4 在應(yīng)用中使用
在主應(yīng)用文件 app.js
中:
require('dotenv').config(); const express = require('express'); const bodyParser = require('body-parser'); const cors = require('cors'); const { sequelize, testConnection } = require('./config/database'); const app = express(); // 中間件 app.use(cors()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); // 測(cè)試數(shù)據(jù)庫(kù)連接 testConnection(); // 路由 app.get('/', function (req, res) { res.send('hello, express'); }); // 啟動(dòng)服務(wù)器 const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`服務(wù)器運(yùn)行在端口 ${PORT}`); });
3. 問題
在實(shí)際連接過程中,我遇到了各種各樣的問題,下面逐一解決。
3.1 MySQL 用戶權(quán)限問題
問題現(xiàn)象:
Access denied for user ''@'localhost' (using password: YES)
解決方案: 在 MySQL 服務(wù)器上創(chuàng)建允許遠(yuǎn)程連接的用戶:
# 登錄 MySQL mysql -u root -p # 查看用戶權(quán)限 SELECT user, host FROM mysql.user WHERE user = 'yel_test'; # 如果用戶不存在,創(chuàng)建新用戶 CREATE USER 'yel_test'@'%' IDENTIFIED BY '123456'; GRANT ALL PRIVILEGES ON yel_test.* TO 'yel_test'@'%'; # 如果用戶已存在但只允許本地連接,添加遠(yuǎn)程連接權(quán)限 GRANT ALL PRIVILEGES ON yel_test.* TO 'yel_test'@'%' IDENTIFIED BY '123456'; # 刷新權(quán)限 FLUSH PRIVILEGES;
3.2 MySQL 配置限制
問題現(xiàn)象:
ConnectionError [SequelizeConnectionError]: connect ETIMEDOUT
解決方案: 修改 MySQL 配置文件(通常是 /etc/my.cnf
),添加或修改 bind-address
設(shè)置:
查找配置文件
# 查找主要配置文件 cat /etc/my.cnf | grep bind-address # 如果上面沒有結(jié)果,查看是否有包含的配置目錄 cat /etc/my.cnf | grep "!includedir" # 修改配置文件 vi /etc/my.cnf
如果使用 vi 但不熟悉:
- 按 i 進(jìn)入插入模式
- 移動(dòng)到 [mysqld] 部分下方
- 添加 bind-address = 0.0.0.0
- 按 Esc 退出插入模式
- 輸入 :wq 保存并退出(或 :q! 不保存退出)
然后重啟 MySQL 服務(wù):
systemctl restart mysqld # 或 service mysqld restart
3.4 防火墻限制
問題現(xiàn)象:
無法連接到數(shù)據(jù)庫(kù),但可以 ping 通服務(wù)器。
解決方案:
檢查并開放服務(wù)器防火墻的 MySQL 端口(默認(rèn) 3306):
# 查看防火墻規(guī)則 firewall-cmd --list-all | grep 3306 # 如果沒有開放,添加規(guī)則 firewall-cmd --zone=public --add-port=3306/tcp --permanent firewall-cmd --reload
3.5 云服務(wù)提供商安全組設(shè)置
問題現(xiàn)象:
即使服務(wù)器防火墻已經(jīng)開放端口,仍然無法連接。
解決方案:
在云服務(wù)提供商的控制面板中,確保安全組規(guī)則允許 3306 端口的入站流量:
允許 | MySQL 訪問 | TCP:3306/3306 | IPv4 | 任何位置 (0.0.0.0/0)
3.6 VPN 導(dǎo)致的連接問題
問題現(xiàn)象:
即使所有配置都正確,仍然出現(xiàn) ETIMEDOUT
錯(cuò)誤。
解決方案:
關(guān)閉 VPN。VPN 可能會(huì)導(dǎo)致網(wǎng)絡(luò)路由沖突,使得到數(shù)據(jù)庫(kù)服務(wù)器的流量被錯(cuò)誤地路由。
VPN 導(dǎo)致連接失敗的原因包括:
- 網(wǎng)絡(luò)路由沖突
- VPN 安全策略限制
- VPN 網(wǎng)絡(luò)延遲
- DNS 解析問題
4. 總結(jié)
連接遠(yuǎn)程 MySQL 數(shù)據(jù)庫(kù)看似簡(jiǎn)單,實(shí)際上涉及多個(gè)層面的配置:
- 應(yīng)用層面:正確配置連接參數(shù)、環(huán)境變量和錯(cuò)誤處理
- 數(shù)據(jù)庫(kù)層面:用戶權(quán)限、MySQL 配置
- 服務(wù)器層面:防火墻設(shè)置、端口開放
- 網(wǎng)絡(luò)層面:安全組規(guī)則、VPN 設(shè)置、網(wǎng)絡(luò)路由
到此這篇關(guān)于淺談express 連接在線數(shù)據(jù)庫(kù)踩坑的文章就介紹到這了,更多相關(guān)express 連接在線數(shù)據(jù)庫(kù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Nodejs高擴(kuò)展性的模板引擎 functmpl簡(jiǎn)介
本文給大家分享的是一款nodejs高擴(kuò)展性的模板引擎functmpl的簡(jiǎn)單介紹以及用法詳解,有需要的小伙伴可以參考下2017-02-02Node.js中使用Log.io在瀏覽器中實(shí)時(shí)監(jiān)控日志(等同tail -f命令)
這篇文章主要介紹了Node.js中使用Log.io在瀏覽器中實(shí)時(shí)監(jiān)控日志,Log.io等同于tail -f命令,但更強(qiáng)大,需要的朋友可以參考下2014-09-09node.js實(shí)現(xiàn)微信JS-API封裝接口的示例代碼
這篇文章主要介紹了node.js實(shí)現(xiàn)微信JS-API封裝接口的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09node.js連接mongoDB數(shù)據(jù)庫(kù) 快速搭建自己的web服務(wù)
這篇文章主要為大家詳細(xì)介紹了node.js連接mongoDB數(shù)據(jù)庫(kù),如何快速搭建自己的web服務(wù),感興趣的小伙伴們可以參考一下2016-04-04node.js使用net模塊創(chuàng)建服務(wù)器和客戶端示例【基于TCP協(xié)議】
這篇文章主要介紹了node.js使用net模塊創(chuàng)建服務(wù)器和客戶端,結(jié)合實(shí)例形式分析了node.js使用net模塊實(shí)現(xiàn)TCP客戶端與服務(wù)器端通信的相關(guān)操作技巧,需要的朋友可以參考下2020-02-02