node.js + mysql 연결 풀링
MySQL을 가장 효율적으로 사용하도록 애플리케이션을 구성하는 방법을 알아 내려고합니다. node-mysql 모듈을 사용하고 있습니다. 여기에 다른 스레드는 연결 풀링을 사용하도록 제안했기 때문에 mysql.js 모듈을 설정했습니다.
var mysql = require('mysql');
var pool = mysql.createPool({
host : 'localhost',
user : 'root',
password : 'root',
database : 'guess'
});
exports.pool = pool;
이제 mysql을 쿼리 할 때마다이 모듈이 필요한 다음 databse를 쿼리합니다.
var mysql = require('../db/mysql').pool;
var test = function(req, res) {
mysql.getConnection(function(err, conn){
conn.query("select * from users", function(err, rows) {
res.json(rows);
})
})
}
이 방법이 좋은가요? 모든 것이 주요 app.js 스크립트에서 수행되는 매우 간단한 것 외에 mysql 연결을 사용하는 예제를 너무 많이 찾을 수 없으므로 규칙 / 모범 사례가 무엇인지 실제로 알지 못합니다.
각 쿼리 후에 항상 connection.end ()를 사용해야합니까? 어딘가에서 잊어 버리면 어떡하죠?
매번 getConnection ()을 쓸 필요가 없도록 mysql 모듈의 내보내기 부분을 다시 작성하여 연결 만 반환하는 방법은 무엇입니까?
좋은 접근 방식입니다.
연결 만 얻으려면 풀이있는 모듈에 다음 코드를 추가하십시오.
var getConnection = function(callback) {
pool.getConnection(function(err, connection) {
callback(err, connection);
});
};
module.exports = getConnection;
매번 getConnection을 작성해야합니다. 그러나 처음으로 연결을 얻을 때 모듈에 연결을 저장할 수 있습니다.
사용이 끝나면 연결을 종료하는 것을 잊지 마십시오.
connection.release();
이 래퍼가 유용하다는 것을 알게 될 것입니다. :)
var pool = mysql.createPool(config.db);
exports.connection = {
query: function () {
var queryArgs = Array.prototype.slice.call(arguments),
events = [],
eventNameIndex = {};
pool.getConnection(function (err, conn) {
if (err) {
if (eventNameIndex.error) {
eventNameIndex.error();
}
}
if (conn) {
var q = conn.query.apply(conn, queryArgs);
q.on('end', function () {
conn.release();
});
events.forEach(function (args) {
q.on.apply(q, args);
});
}
});
return {
on: function (eventName, callback) {
events.push(Array.prototype.slice.call(arguments));
eventNameIndex[eventName] = callback;
return this;
}
};
}
};
필요하면 다음과 같이 사용하십시오.
db.connection.query("SELECT * FROM `table` WHERE `id` = ? ", row_id)
.on('result', function (row) {
setData(row);
})
.on('error', function (err) {
callback({error: true, err: err});
});
이 기본 클래스 연결을 mysql과 함께 사용하고 있습니다.
"base.js"
var mysql = require("mysql");
var pool = mysql.createPool({
connectionLimit : 10,
host: Config.appSettings().database.host,
user: Config.appSettings().database.username,
password: Config.appSettings().database.password,
database: Config.appSettings().database.database
});
var DB = (function () {
function _query(query, params, callback) {
pool.getConnection(function (err, connection) {
if (err) {
connection.release();
callback(null, err);
throw err;
}
connection.query(query, params, function (err, rows) {
connection.release();
if (!err) {
callback(rows);
}
else {
callback(null, err);
}
});
connection.on('error', function (err) {
connection.release();
callback(null, err);
throw err;
});
});
};
return {
query: _query
};
})();
module.exports = DB;
다음과 같이 사용하십시오.
var DB = require('../dal/base.js');
DB.query("select * from tasks", null, function (data, error) {
callback(data, error);
});
pool.getConnection()
가능하면 사용을 피해야 합니다. 당신이 호출 할 경우 pool.getConnection()
, 당신은 해야한다 전화 connection.release()
는 연결을 사용하여 수행하는 경우. 그렇지 않으면 연결 제한에 도달하면 연결이 풀로 반환 될 때까지 응용 프로그램이 영원히 대기 상태가됩니다.
간단한 쿼리의 경우 pool.query()
. 이 속기는 connection.release()
오류 상태에서도 자동으로 호출 됩니다.
function doSomething(cb) {
pool.query('SELECT 2*2 "value"', (ex, rows) => {
if (ex) {
cb(ex);
} else {
cb(null, rows[0].value);
}
});
}
그러나 어떤 경우에는 pool.getConnection()
. 이러한 경우는 다음과 같습니다.
- 트랜잭션 내에서 여러 쿼리 만들기.
- 후속 쿼리간에 임시 테이블과 같은 데이터 개체를 공유합니다.
을 사용해야하는 경우 아래와 유사한 패턴을 사용하여 pool.getConnection()
호출 해야합니다 connection.release()
.
function doSomething(cb) {
pool.getConnection((ex, connection) => {
if (ex) {
cb(ex);
} else {
// Ensure that any call to cb releases the connection
// by wrapping it.
cb = (cb => {
return function () {
connection.release();
cb.apply(this, arguments);
};
})(cb);
connection.beginTransaction(ex => {
if (ex) {
cb(ex);
} else {
connection.query('INSERT INTO table1 ("value") VALUES (\'my value\');', ex => {
if (ex) {
cb(ex);
} else {
connection.query('INSERT INTO table2 ("value") VALUES (\'my other value\')', ex => {
if (ex) {
cb(ex);
} else {
connection.commit(ex => {
cb(ex);
});
}
});
}
});
}
});
}
});
}
나는 개인적으로 Promise
s와 useAsync()
패턴 을 사용하는 것을 선호합니다 . 이 패턴을 async
/ 와 결합 await
하면 release()
어휘 범위 지정이 다음과 같은 자동 호출로 바뀌기 때문에 실수로 연결을 잊어 버리는 것을 훨씬 더 어렵게 만듭니다 .release()
.
async function usePooledConnectionAsync(actionAsync) {
const connection = await new Promise((resolve, reject) => {
pool.getConnection((ex, connection) => {
if (ex) {
reject(ex);
} else {
resolve(connection);
}
});
});
try {
return await actionAsync(connection);
} finally {
connection.release();
}
}
async function doSomethingElse() {
// Usage example:
const result = await usePooledConnectionAsync(async connection => {
const rows = await new Promise((resolve, reject) => {
connection.query('SELECT 2*4 "value"', (ex, rows) => {
if (ex) {
reject(ex);
} else {
resolve(rows);
}
});
});
return rows[0].value;
});
console.log(`result=${result}`);
}
연결이 완료되면 전화 만하면 connection.release()
연결이 풀로 돌아가서 다른 사람이 다시 사용할 수 있습니다.
var mysql = require('mysql');
var pool = mysql.createPool(...);
pool.getConnection(function(err, connection) {
// Use the connection
connection.query('SELECT something FROM sometable', function (error, results, fields) {
// And done with the connection.
connection.release();
// Handle error after the release.
if (error) throw error;
// Don't use the connection here, it has been returned to the pool.
});
});
연결을 닫고 풀에서 제거하려면 connection.destroy()
대신 사용하십시오. 풀은 다음에 필요할 때 새 연결을 만듭니다.
출처 : https://github.com/mysqljs/mysql
표준 mysql.createPool ()을 사용하면 연결이 풀에 의해 느리게 생성됩니다. 최대 100 개의 연결을 허용하도록 풀을 구성하지만 동시에 5 개만 사용하는 경우 5 개만 연결됩니다. 그러나 500 개의 연결로 구성하고 500 개를 모두 사용하면 유휴 상태 인 경우에도 프로세스 기간 동안 열린 상태로 유지됩니다!
즉, MySQL Server max_connections가 510이면 MySQL 서버가 연결을 닫거나 (wait_timeout을 설정 한 값에 따라) 애플리케이션이 닫힐 때까지 시스템에 10 개의 mySQL 연결 만 사용할 수 있습니다. 이를 해제하는 유일한 방법은 풀 인스턴스를 통해 연결을 수동으로 닫거나 풀을 닫는 것입니다.
mysql-connection-pool-manager 모듈은이 문제를 해결하고로드에 따라 자동으로 연결 수를 조정하기 위해 생성되었습니다. 활동이없는 경우 비활성 연결이 닫히고 유휴 연결 풀이 결국 닫힙니다.
// Load modules
const PoolManager = require('mysql-connection-pool-manager');
// Options
const options = {
...example settings
}
// Initialising the instance
const mySQL = PoolManager(options);
// Accessing mySQL directly
var connection = mySQL.raw.createConnection({
host : 'localhost',
user : 'me',
password : 'secret',
database : 'my_db'
});
// Initialising connection
connection.connect();
// Performing query
connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
if (error) throw error;
console.log('The solution is: ', results[0].solution);
});
// Ending connection
connection.end();
참고 : https://www.npmjs.com/package/mysql-connection-pool-manager
나는 항상 connection.relase (); pool.getconnetion 후
pool.getConnection(function (err, connection) {
connection.release();
if (!err)
{
console.log('*** Mysql Connection established with ', config.database, ' and connected as id ' + connection.threadId);
//CHECKING USERNAME EXISTENCE
email = receivedValues.email
connection.query('SELECT * FROM users WHERE email = ?', [email],
function (err, rows) {
if (!err)
{
if (rows.length == 1)
{
if (bcrypt.compareSync(req.body.password, rows[0].password))
{
var alldata = rows;
var userid = rows[0].id;
var tokendata = (receivedValues, userid);
var token = jwt.sign(receivedValues, config.secret, {
expiresIn: 1440 * 60 * 30 // expires in 1440 minutes
});
console.log("*** Authorised User");
res.json({
"code": 200,
"status": "Success",
"token": token,
"userData": alldata,
"message": "Authorised User!"
});
logger.info('url=', URL.url, 'Responce=', 'User Signin, username', req.body.email, 'User Id=', rows[0].id);
return;
}
else
{
console.log("*** Redirecting: Unauthorised User");
res.json({"code": 200, "status": "Fail", "message": "Unauthorised User!"});
logger.error('*** Redirecting: Unauthorised User');
return;
}
}
else
{
console.error("*** Redirecting: No User found with provided name");
res.json({
"code": 200,
"status": "Error",
"message": "No User found with provided name"
});
logger.error('url=', URL.url, 'No User found with provided name');
return;
}
}
else
{
console.log("*** Redirecting: Error for selecting user");
res.json({"code": 200, "status": "Error", "message": "Error for selecting user"});
logger.error('url=', URL.url, 'Error for selecting user', req.body.email);
return;
}
});
connection.on('error', function (err) {
console.log('*** Redirecting: Error Creating User...');
res.json({"code": 200, "status": "Error", "message": "Error Checking Username Duplicate"});
return;
});
}
else
{
Errors.Connection_Error(res);
}
});
참고 URL : https://stackoverflow.com/questions/18496540/node-js-mysql-connection-pooling
'Development Tip' 카테고리의 다른 글
MSI 설정은 어떻게 생성합니까? (0) | 2020.11.18 |
---|---|
Docker를 사용하여 컨테이너에 할당 된 리소스를 어떻게 설정합니까? (0) | 2020.11.18 |
ggplot에 대한 curve ()와 동일 (0) | 2020.11.18 |
사전에서 defaultdict를 구성하는 방법은 무엇입니까? (0) | 2020.11.18 |
사용시기 (0) | 2020.11.18 |