【发布时间】:2020-12-20 00:52:44
【问题描述】:
几个月来我一直在构建一个 SaaS 平台,当我开始扩展时,我遇到了一笔巨额 GCP Cloud SQL 账单,这让我意识到我没有正确处理我的连接。
我在 Node.js 上使用 MySQL 5.7 和 mysqljs。这是一个用 Vue 构建的 SPA。它分为客户端和服务器。云 MySQL 数据库的 MySQL 凭据保存在 GCP Cloud Firestore 中。当最终用户登录时,他们的数据库信息将从 Firestore 中检索并保存在客户端的状态管理区域中。
这是当前的数据流(自下而上)
CGP Cloud SQL Database - Stores all of the bulk account data.
⬆
Server - responsible for transferring data between the Google Cloud SQL Database and the Client.
⬆
Client - Responsible for UI and basic logic. Stores SQL connection string behind the scenes to send to the server with queries.
⬆
Cloud Firestore - Stores 'environment variables' for the end users (MySQL database login data) which is sent to the client after authentication.
⬆
Firebase authentication - OAuth to ensure the proper party is logged in before retrieving their database information from Firestore and allowing access to the app.
当需要运行 MySQL 查询时,参数以及 SQL 数据库连接字符串/对象会从客户端传递到服务器。服务器进行查询,然后将结果发送回客户端。
这意味着每次进行查询时都会建立新的连接。因此,如果此人碰巧快速浏览帐户,他们可能会非常快速地进行大量查询。
自从我实施了这个系统后,我的 GCP 云 SQL 账单猛增。考虑到敏感信息保存在 Firestore 中,我想我可以将 Vue 客户端直接连接到数据库,数据库访问是 IP 敏感的,最终用户甚至不知道它是后端的 MySQL 数据库。
我不知道这是否是糟糕的架构。我需要一点指导。我正计划迁移到 Firebase Cloud Functions,因此我的服务器当前设置为好像它是几十个独立功能,例如:
getAccountsByStatus()
showAccountDataById()
notateAccountByFileNumber()
etc...
这是一个例子:
客户
this.searchValue = this.$route.params.name;
axios
.post(`${rootUrl}/api/v1/search/name`, {
searchName: this.searchValue,
host: this.serverDBase,
user: this.userDBase,
password: this.passDBase,
schema: this.schemaDBase,
})
.then((response) => (this.searchResults = response.data))
.finally(this.updateOverlay)
.catch((error) => {
throw error;
});
服务器
//* Search by name
app.post(`/api/v1/search/name`, (req, res) => {
let fullName = req.body.searchName;
let host = req.body.host;
let user = req.body.user;
let password = req.body.password;
let schema = req.body.schema;
// DELETED SANITIZATON BLOCK 1 FOR BREVITY
let selectStatement = `SELECT id, file_number, full_name, balance FROM devdb.primary WHERE fullname LIKE '%${full_name}%'`;
// DELETED SANITIZATON BLOCK 2 FOR BREVITY
let connection = mysql.createConnection({
host: host,
user: user,
password: password,
database: schema,
port: 3306,
});
if (connection.state === 'disconnected') {
connection.connect();
}
connection.query(selectStatement.toString(), (err, results) => {
if (err) {
console.log(err);
} else if (results.length() == 0) {
res.send([]);
return;
}
res.send(results);
});
});
在这种情况下通常会怎么做?考虑到它已经来自安全的 Firestore 数据库,将连接保存在 Vue 客户端实例中并进行直接查询?连接池?还是完全不同的东西?
【问题讨论】:
-
通常你会做连接池,如果配置得当,MySQL 可以轻松处理数千个连接。如果不够,请使用 MySQL 代理,其中有几个很棒的代理可供选择。
标签: mysql sql node.js firebase nodejs-server