수영장 파티! Node.js의 MySQL 풀 연결 💦🔌
const express = require('express');
const app = express();
const mysql = require('mysql');
const db_connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'test'
});
db_connection.connect((err) => {
if (err) console.error(err);
console.log('MySQL Connection Established.');
});
const getUsers = () => new Promise((resolve, reject) => {
db_connection.query('SELECT * FROM USERS', (err, results) => {
if (err) console.error(err);
console.log('User Query Results: ', results);
resolve(results);
db_connection.end(err => { if (err) console.error(err) });
});
});
app.get('/', (req, res) => {
getUsers()
.then(users => res.send(users))
.catch(err => console.error(err));
});
app.listen(8080, () => {
console.log('Server listening on port 8080.');
});
이 간단한 서버는 데이터베이스 연결을 설정하고 "users"테이블(하나의 항목이 미리 로드됨)의 모든 행에 대해 "test"(이전에 생성됨)라는 데이터베이스를 쿼리합니다.
node app.js
로 서버를 시작한 후 http://localhost:8080
에 대한 Postman GET 호출은 예상 응답을 다시 보냅니다.[
{
"id": 1,
"username": "gdup",
"location": "New Orleans"
}
]
그리고 터미널에서:
Server listening on port 8080.
MySQL Connection Established.
User Query Results: [ RowDataPacket { id: 1, username: 'gdup', location: 'New Orleans' } ]
그러나 후속 Postman 호출은 빈 응답을 생성하고 오류와 함께 서버를 종료합니다.
User Query Results: undefined
Error: Cannot enqueue Quit after invoking quit.
at Protocol._validateEnqueue (/Users/Work/immersion/database-test/node_modules/mysql/lib/protocol/Protocol.js:215:16)
at Protocol._enqueue (/Users/Work/immersion/database-test/node_modules/mysql/lib/protocol/Protocol.js:138:13)
at Protocol.quit (/Users/Work/immersion/database-test/node_modules/mysql/lib/protocol/Protocol.js:91:23)
at Connection.end (/Users/Work/immersion/database-test/node_modules/mysql/lib/Connection.js:239:18)
at Query.<anonymous> (/Users/Work/immersion/database-test/app.js:22:19)
at Query.<anonymous> (/Users/Work/immersion/database-test/node_modules/mysql/lib/Connection.js:526:10)
at Query._callback (/Users/Work/immersion/database-test/node_modules/mysql/lib/Connection.js:488:16)
at Query.Sequence.end (/Users/Work/immersion/database-test/node_modules/mysql/lib/protocol/sequences/Sequence.js:83:24)
at /Users/Work/immersion/database-test/node_modules/mysql/lib/protocol/Protocol.js:236:14
at processTicksAndRejections (internal/process/task_queues.js:79:11) {
code: 'PROTOCOL_ENQUEUE_AFTER_QUIT',
fatal: false
}
여기서 문제는 데이터베이스 연결의
db_connection.end()
부분입니다. 연결이 종료되면 다시 시작할 수 없으며 다시 사용할 수 없습니다. "그냥 연결을 끊지 않는 게 어때?"스스로에게 물어볼 수도 있습니다. 글쎄요, 데이터베이스에 대한 단일 생명선에 문제가 없는 한 괜찮습니다. 그러나 그 외에도 더 많은 유연성을 원하는 다른 이유가 있습니다. 하나는 결국 여러 동시 사용자에 대해 여러 연결을 가질 수 있어야 할 것입니다. 마찬가지로, 결국 둘 이상의 연결이 필요한 쿼리를 구현하려고 할 수 있습니다. 연결을 통해 수행되는 모든 쿼리는 순차적이라는 점에 유의하십시오. 각각 1초가 걸리는 쿼리가 10개 있는 경우 총 실행 시간은 물론 병렬로 실행되지 않는 한 10초가 됩니다.siege
를 설치하여 데모의 한 부분을 더 설정해 보겠습니다. 그러면 동시 get 요청으로 서버를 폭발시킬 수 있습니다. benchmark.js
파일에서 다음 코드를 사용하면 node benchmark.js
를 실행하여 이를 수행할 수 있습니다.const siege = require('siege');
siege()
.on(8080)
.concurrent(10)
.get('/')
.attack();
서버를 시작하고 실행
node benchmark.js
하면 예상대로 서버가 종료되고 위에서 Postman이 수행한 것과 동일한 오류가 생성됩니다. 이제 연결을 리팩토링해 보겠습니다.const express = require('express');
const app = express();
const mysql = require('mysql');
const db_connection = mysql.createPool({
host: 'localhost',
user: 'root',
password: '',
database: 'test'
});
const getUsers = () => new Promise((resolve, reject) => {
db_connection.getConnection((err, connection) => {
if (err) console.error(err);
console.log('MySQL Connection Established: ', connection.threadId);
connection.query('SELECT * FROM USERS', (err, results) => {
if (err) console.error(err);
console.log('User Query Results: ', results);
resolve(results);
connection.release(err => { if (err) console.error(err) });
});
});
});
app.get('/', (req, res) => {
getUsers()
.then(users => res.send(users))
.catch(err => console.error(err));
});
app.listen(8080, () => {
console.log('Server listening on port 8080.');
});
이제
createConnection
대신 createPool
를 사용하여 연결 풀을 빌릴 준비가 되었습니다. 때가 되면 getConnection
와 connection
를 콜백 함수의 매개변수로 사용합니다. 풀이 제공하는 연결이 쿼리에 사용할 연결입니다. 이제 시즈 테스트를 실행하면 서버를 중단하지 않고 여러 쿼리 결과 집합이 생성됩니다. 다음은 몇 가지입니다.Server listening on port 8080.
MySQL Connection Established: 124
MySQL Connection Established: 123
User Query Results: [ RowDataPacket { id: 1, username: 'gdup', location: 'New Orleans' } ]
User Query Results: [ RowDataPacket { id: 1, username: 'gdup', location: 'New Orleans' } ]
MySQL Connection Established: 123
MySQL Connection Established: 124
MySQL Connection Established: 125
User Query Results: [ RowDataPacket { id: 1, username: 'gdup', location: 'New Orleans' } ]
User Query Results: [ RowDataPacket { id: 1, username: 'gdup', location: 'New Orleans' } ]
MySQL Connection Established: 126
User Query Results: [ RowDataPacket { id: 1, username: 'gdup', location: 'New Orleans' } ]
User Query Results: [ RowDataPacket { id: 1, username: 'gdup', location: 'New Orleans' } ]
console.log
의 connection.threadId
는 각 연결에 대해 고유한 번호를 표시합니다. 사용된 연결 범위를 보여줍니다. 실제로 생성할 개수를 지정하지 않았지만 기본값은 100입니다. 연결 매개변수에서 제한을 1로 설정하면:const db_connection = mysql.createPool({
host: 'localhost',
user: 'root',
password: '',
database: 'test',
connectionLimit: 1,
});
...공성 공격을 다시 실행하면 동일한 단일 풀 연결이 계속해서 사용됩니다.
Server listening on port 8080.
MySQL Connection Established: 131
User Query Results: [ RowDataPacket { id: 1, username: 'gdup', location: 'New Orleans' } ]
MySQL Connection Established: 131
User Query Results: [ RowDataPacket { id: 1, username: 'gdup', location: 'New Orleans' } ]
MySQL Connection Established: 131
User Query Results: [ RowDataPacket { id: 1, username: 'gdup', location: 'New Orleans' } ]
MySQL Connection Established: 131
User Query Results: [ RowDataPacket { id: 1, username: 'gdup', location: 'New Orleans' } ]
MySQL Connection Established: 131
User Query Results: [ RowDataPacket { id: 1, username: 'gdup', location: 'New Orleans' } ]
쿼리 끝에 있는
connection.release()
를 기록해 둡니다. 이것은 연결이 풀에 다시 제공되어 재사용되는 방정식의 중요한 부분입니다. 마치 도서관에서 책을 빌린 후 반환하는 것과 같습니다. 그리고 이전과 마찬가지로 필요한 경우 db_connection.end()
로 모든 연결을 (동시에) 닫을 수 있습니다.MySQL/Node.js 풀 연결에 대한 이 튜토리얼이 도움이 되었기를 바랍니다. 풀 연결은 처음에는 신비하게 보일 수 있으며 "내부"에서 작동하는 방식은 즉시 명확하지 않습니다. 그러나 위의 실험을 통해 기능에 대한 구체적인 이해를 얻었고 이제 풀 연결을 구현하는 것이 쉬울 뿐만 아니라 매우 유익하다는 데 동의할 수 있기를 바랍니다.
Reference
이 문제에 관하여(수영장 파티! Node.js의 MySQL 풀 연결 💦🔌), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/gduple/pool-party-mysql-pool-connections-in-node-js-3om7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)