连接/断开数据库的最佳实践是啥?

Posted

技术标签:

【中文标题】连接/断开数据库的最佳实践是啥?【英文标题】:What is the best practice to connect/disconnect to a database?连接/断开数据库的最佳实践是什么? 【发布时间】:2016-04-06 02:48:42 【问题描述】:

我想知道如何在 MEAN 堆栈应用程序中使用与数据库的连接。特别是,我应该何时创建与数据库的连接以及何时应销毁与数据库的连接。我应该在每个新的 HTTP 请求上创建和销毁连接,还是应该存储一次创建的连接并尽可能长时间地将其用于任何后续请求。我使用 Mongoose 作为建模工具。

这是一个例子。 这是我的routes.js 文件,路径为/index。对该路由的请求应该从 MongoDb 数据库中获取一些日期。我现在如何连接和断开数据库让我很困扰。是的,我完全按照 Mongoose 文档中的说明连接和断开数据库,但这是在严肃的生产环境中执行此操作的正确方法吗?

var express = require('express');
var router = express.Router();

var config = require('./db-config');

// I create a Mongoose instance as a module object,
// as opposite to create it in every request handler function below.
var mongoose = require('mongoose');

var productSchema = require('../db/productSchema'); // model schema is also a module-wide object

// And here is a request handler function.
// It is called on every request as a brand new.
// I create and destroy a database connection inside this request handler
router.get('/index', function(req, res, next) 

    // I connect to a database on every request.
    // Do I need to do it here in a request handler?
    // May I do it outside of this request handler on a module-wide level?
    mongoose.connect('mongodb://my_database');

    // I create a new connection here in a request handler.
    // So it lives only during this request handler run.
    // Is this the right way? May I do it outside of this request handler 
    // on a module-wide level and somehow keep this connection and use it 
    // in every subsequent requests to this or any other route in the app?
    var db = mongoose.connection;

    db.on('connecting', function() 
        console.log('connecting');
    );

    db.on('connected', function() 
        console.log('connected');
    );

    db.on('open', function() 
        console.log('open');
    );

    db.on('error', console.error.bind(console, 'connection error'));

    db.once('open', function(cb) 
        var Product = mongoose.model('Product', productSchema);
        Product.find(category: "books", function(err, prods) 
            if (err) return console.error(err);

            // I close a connection here in a callback. 
            // As soon as successfully fetched the data. 
            // Do I need to close it after every request? 
            // What is the right place and time to do it? 
            db.close(disconnect);
            res.json(prods);
        );
    );
)

找到了一些好的答案:

https://softwareengineering.stackexchange.com/questions/142065/creating-database-connections-do-it-once-or-for-each-query

What are best practices on managing database connections in .NET?

【问题讨论】:

【参考方案1】:

将数据库连接放在单独的模块 (db.js) 中的最佳做法

var mongoose = require('mongoose')

mongoose.connect('mongodb://localhost/dbname', function()
    console.log('mongodb connected')
)
module.exports = mongoose

每个模型都应该有一个单独的模块来接收数据库连接(post.js)

var db = require('../db.js')
var Post = db.model('Post', 
    username: type: String, required: true,
    body: type: String, required: true,
    date:  type: Date, required: true, default: Date.now   
)

module.exports = Post

然后,当您需要使用该数据集时,只需要求它并进行调用

var Post = require('/models/post')
Post.save()
Post.find()

【讨论】:

【参考方案2】:

我会说这是一个基于意见的问题。我用于我的应用程序的是

app.get('/', function (req, res) 
res.sendfile('index.html');
);
mongoose.connect('mongodb://localhost:27017/my_db'); 

这样我创建一个连接一次,而不是在每个 HTTP 请求上。您的方式应该可以正常工作,但似乎您必须多次将数据库连接和断开连接到您的应用程序,特别是在应用程序正在开发时。

【讨论】:

【参考方案3】:

您希望您的连接表现得像一个单身人士,所以正如上面的答案中提到的那样,在您的路线之外并且最好在您的路线之前进行它是有意义的:

var compression = require('compression');
var express  = require('express');
var app      = express();
var port     = process.env.PORT || 8080;
var cookieParser = require('cookie-parser');
var bodyParser   = require('body-parser');
var session      = require('express-session');
...

app.use(compression());
// db
var mongoose = require('mongoose');
var configDB = require('./config/database.js');
mongoose.connect(configDB.url); // connect to our database

config/database.js:

module.exports = 
'url' : '@localhost:27017/dbname'
;

【讨论】:

mongoose.connect 是异步的。如何确保在路由之前数据库连接已准备就绪?【参考方案4】:

这是我的解决方案:

import express from 'express';
import mongoose from 'mongoose';
import  name  from '../package.json';
import * as localconfig from './local-config';
import debug from 'debug';
debug(name);
const app = express();

const port = process.env.PORT || 3000;
const mongoUrl = localconfig.credentials.MONGO_URL;

import usersRoutes from './routes/users/user-routes';

app.use('/v1/users', usersRoutes);

mongoose.connect(mongoUrl)
    .then(() => 
        debug('DB connection successful');
        app.listen(port, '0.0.0.0', () => 
            debug(`Running on port $port`);
        );
    )
    .catch((err) => 
        debug(err);
    );

您应该首先检查连接是否成功,然后才能监听某个端口。这是我的app.js 文件,其中加载了所有路由,因此您不必在所有文件中调用数据库连接。您有一个配置文件,所有配置都在其中完成。您的路由器文件user-routes.js 将类似于以下内容:

import express from 'express';

import User from '../models/user'
const router = express.Router();

router.get('/', (req, res, next) => 
    User.find()
        .then((response) => res.json(response))
        .catch((err) => next(err));
);

module.exports = router;

【讨论】:

欢迎来到 Stack Overflow!请不要只用源代码回答。尝试对您的解决方案如何工作提供一个很好的描述。见:How do I write a good answer?。谢谢 这个问题主要是指导性的,所以尝试添加一些推理,为什么您的解决方案比他们已经拥有的解决方案更好

以上是关于连接/断开数据库的最佳实践是啥?的主要内容,如果未能解决你的问题,请参考以下文章

向客户端发送数据的最佳实践是啥:POCO 还是 DTO?

处理中途断开连接的控制器的最佳做法是啥?

带有 Ambari 的 NiFi 集群 - 维护的最佳实践是啥?

Node.js 上 MongoDB 连接的最佳实践是啥?

DAO(数据访问对象)最佳实践 - 我看到的示例同时使用 DAO 和服务对象,这里的最佳实践是啥?

Firestore 数据结构的最佳实践是啥?