express 连接在线数据库踩坑

1. 前言

在学习 Node.js 开发的过程中,Express 框架无疑是最受欢迎的选择之一。

作为一名前端开发者,我决定深入学习后端技术,搭建一个完整的博客系统。

第一步自然是连接数据库,而我选择了连接远程服务器上的 MySQL 数据库,而不是在本地搭建环境。

这看似简单的一步,却让我遇到了各种各样的问题。

本文将记录我在连接远程 MySQL 数据库过程中遇到的各种坑,希望能帮助到同样遇到困难的开发者。

2. 如何连接

2.1 环境准备

首先,我们需要安装必要的依赖:

bash 复制代码
npm install express mysql2 sequelize dotenv

2.2 配置文件

为了安全管理数据库连接信息,我创建了 .env 文件来存储敏感信息:

数据库配置

ini 复制代码
DB_HOST=your_server_ip
DB_PORT=3306
DB_NAME=your_database_name
DB_USER=your_username
DB_PASSWORD=your_password

服务器配置

ini 复制代码
PORT=3000
NODE_ENV=development

2.3 数据库连接配置

然后创建 config/database.js 文件:

javascript 复制代码
const { Sequelize } = require('sequelize');
require('dotenv').config();

// 从环境变量获取数据库配置
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 || '';

// 创建 Sequelize 实例,连接到远程数据库
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
  }
);

// 测试数据库连接
const testConnection = async () => {
  try {
    await sequelize.authenticate();
    console.log('数据库连接成功!');
  } catch (error) {
    console.error('无法连接到数据库:', error);
  }
};

module.exports = {
  sequelize,
  testConnection
};

2.4 在应用中使用

在主应用文件 app.js 中:

javascript 复制代码
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 }));

// 测试数据库连接
testConnection();

// 路由
app.get('/', function (req, res) {
  res.send('hello, express');
});

// 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`服务器运行在端口 ${PORT}`);
});

3. 问题

在实际连接过程中,我遇到了各种各样的问题,下面逐一解决。

3.1 MySQL 用户权限问题

问题现象

sql 复制代码
Access denied for user ''@'localhost' (using password: YES)

解决方案: 在 MySQL 服务器上创建允许远程连接的用户:

sql 复制代码
# 登录 MySQL
mysql -u root -p

# 查看用户权限
SELECT user, host FROM mysql.user WHERE user = 'yel_test';

# 如果用户不存在,创建新用户
CREATE USER 'yel_test'@'%' IDENTIFIED BY '123456';
GRANT ALL PRIVILEGES ON yel_test.* TO 'yel_test'@'%';

# 如果用户已存在但只允许本地连接,添加远程连接权限
GRANT ALL PRIVILEGES ON yel_test.* TO 'yel_test'@'%' IDENTIFIED BY '123456';

# 刷新权限
FLUSH PRIVILEGES;

3.2 MySQL 配置限制

问题现象

shell 复制代码
ConnectionError [SequelizeConnectionError]: connect ETIMEDOUT

解决方案 : 修改 MySQL 配置文件(通常是 /etc/my.cnf),添加或修改 bind-address 设置:

查找配置文件

bash 复制代码
# 查找主要配置文件
cat /etc/my.cnf | grep bind-address

# 如果上面没有结果,查看是否有包含的配置目录
cat /etc/my.cnf | grep "!includedir"


# 修改配置文件
vi /etc/my.cnf

如果使用 vi 但不熟悉:

  1. 按 i 进入插入模式

  2. 移动到 [mysqld] 部分下方

  3. 添加 bind-address = 0.0.0.0

  4. 按 Esc 退出插入模式

  5. 输入 :wq 保存并退出(或 :q! 不保存退出)

然后重启 MySQL 服务:

bash 复制代码
systemctl restart mysqld
# 或
service mysqld restart

3.4 防火墙限制

问题现象

无法连接到数据库,但可以 ping 通服务器。

解决方案

检查并开放服务器防火墙的 MySQL 端口(默认 3306):

bash 复制代码
# 查看防火墙规则
firewall-cmd --list-all | grep 3306

# 如果没有开放,添加规则
firewall-cmd --zone=public --add-port=3306/tcp --permanent
firewall-cmd --reload

3.5 云服务提供商安全组设置

问题现象

即使服务器防火墙已经开放端口,仍然无法连接。

解决方案

在云服务提供商的控制面板中,确保安全组规则允许 3306 端口的入站流量:

允许 | MySQL 访问 | TCP:3306/3306 | IPv4 | 任何位置 (0.0.0.0/0)

3.6 VPN 导致的连接问题

问题现象

即使所有配置都正确,仍然出现 ETIMEDOUT 错误。

解决方案

关闭 VPN。VPN 可能会导致网络路由冲突,使得到数据库服务器的流量被错误地路由。

VPN 导致连接失败的原因包括:

  • 网络路由冲突
  • VPN 安全策略限制
  • VPN 网络延迟
  • DNS 解析问题

4. 总结

连接远程 MySQL 数据库看似简单,实际上涉及多个层面的配置:

  1. 应用层面:正确配置连接参数、环境变量和错误处理

  2. 数据库层面:用户权限、MySQL 配置

  3. 服务器层面:防火墙设置、端口开放

  4. 网络层面:安全组规则、VPN 设置、网络路由

相关推荐
前端小盆友4 小时前
从零实现一个GPT 【React + Express】--- 【4】实现文生图的功能
react.js·chatgpt·express
伍哥的传说9 小时前
H3初识——入门介绍之常用中间件
前端·javascript·react.js·中间件·前端框架·node.js·ecmascript
超级土豆粉10 小时前
npm 包 scheduler 介绍
前端·npm·node.js
WildBlue11 小时前
流式输出:前端工程师的魔术表演,小白也能看懂!🎩✨
前端·javascript·node.js
GDAL12 小时前
Node.js Stream 深入全面讲解
node.js
爱分享的程序员1 天前
前端面试专栏-算法篇:20. 贪心算法与动态规划入门
前端·javascript·node.js
我叫黑大帅1 天前
Sequelize:让你和数据库唠嗑像聊微信一样简单 😎
后端·node.js
小山不高1 天前
本地使用minio之前后端关键点
前端·node.js
吓死羊了1 天前
设置nginx和tomcat开机自动启动
后端·node.js·tomcat