Heroku에 node.js 앱을 작성하고 pg 모듈을 사용하고 있습니다. 데이터베이스를 쿼리해야하는 각 요청에 대해 클라이언트 개체를 가져 오는 “올바른”방법을 알아낼 수 없습니다.
문서는 다음과 같은 코드를 사용합니다.
pg.connect(conString, function(err, client) {
// Use the client to do things here
});
그러나 확실히 pg.connect
데이터베이스를 사용하는 모든 함수 내부 를 호출 할 필요 는 없습니까? 이 작업을 수행하는 다른 코드 를 본 적이 있습니다 .
var conString = process.env.DATABASE_URL || "tcp://postgres:1234@localhost/postgres";
var client = new pg.Client(conString);
client.connect();
// client is a global so you can use it anywhere now
Heroku의 무료 데이터베이스 인스턴스가 어쨌든 하나의 연결로 제한되어 있다고 믿기 때문에 두 번째 옵션으로 기울고 있지만 이렇게하는 데 단점이 있습니까? 클라이언트 개체를 사용하기 전에 항상 연결되어 있는지 확인해야합니까?
답변
저는 node-postgres 의 저자입니다 . 첫째, 문서가 올바른 옵션을 명확하게하지 못해 죄송합니다. 그게 내 잘못입니다. 나는 그것을 개선하려고 노력할 것입니다. 트위터에 비해 대화 가 너무 길어 졌기 때문에 이것을 설명하기 위해 방금 요점을 썼습니다 .
사용
pg.connect
은 웹 환경 으로 이동하는 방법 입니다.PostgreSQL 서버는 연결 당 한 번에 하나의 쿼리 만 처리 할 수 있습니다. 즉
new pg.Client()
, 백엔드에 1 개의 글로벌이 연결되어 있으면 postgres가 쿼리에 응답 할 수있는 속도에 따라 전체 앱에 병목 현상이 발생합니다. 말 그대로 모든 것을 정렬하여 각 쿼리를 대기열에 넣습니다. 예, 비동기이므로 괜찮습니다 …하지만 처리량에 10 배를 곱하지 않겠습니까?pg.connect
set the
pg.defaults.poolSize
를 제정신으로 사용하십시오 (우리는 25-100을 수행하지만 올바른 숫자는 아직 확실하지 않습니다).
new pg.Client
당신이 무엇을하고 있는지 알 때입니다. 어떤 이유로 한 명의 장수 클라이언트가 필요하거나 수명주기를 매우 신중하게 제어해야하는 경우. 이에 대한 좋은 예는
LISTEN/NOTIFY
. 청취 클라이언트는NOTIFY
메시지를 적절하게 처리 할 수 있도록 주변에 있고 연결되어 있어야하며 공유되지 않아야 합니다. 다른 예는 일회성 클라이언트를 열어 정지 된 항목이나 명령 줄 스크립트를 종료하는 경우입니다.
한 가지 매우 유용한 것은 앱의 데이터베이스에 대한 모든 액세스를 하나의 파일로 중앙 집중화하는 것입니다. pg.connect
전화 나 신규 고객을 흩 뜨리지 마십시오 . db.js
다음과 같은 파일 을 만드십시오.
module.exports = {
query: function(text, values, cb) {
pg.connect(function(err, client, done) {
client.query(text, values, function(err, result) {
done();
cb(err, result);
})
});
}
}
이렇게하면 구현 pg.connect
을 클라이언트의 사용자 지정 풀로 변경할 수 있으며 한 곳에서만 변경하면됩니다.
이를 수행하는 node-pg-query 모듈 을 살펴보십시오 .
답변
나는 promise 를 통해 node-postgres 의 사용을 단순화하는 pg-promise 의 저자입니다 .
자동화 된 트랜잭션과 같이 node-postgres에 의해 구현 된 연결 풀을 사용하여 데이터베이스에 연결하고 연결을 끊는 올바른 방법에 대한 문제를 해결 합니다.
pg-promise 의 개별 요청은 비즈니스 로직과 관련된 것으로 요약됩니다.
db.any('SELECT * FROM users WHERE status = $1', ['active'])
.then(data => {
console.log('DATA:', data);
})
.catch(error => {
console.log('ERROR:', error);
});
즉, 다음과 같이 전역 적으로 한 번만 연결을 설정하기 때문에 쿼리를 실행할 때 연결 논리를 다룰 필요가 없습니다.
const pgp = require('pg-promise')(/*options*/);
const cn = {
host: 'localhost', // server name or IP address;
port: 5432,
database: 'myDatabase',
user: 'myUser',
password: 'myPassword'
};
// alternative:
// const cn = 'postgres://username:password@host:port/database';
const db = pgp(cn); // database instance;
Learn by Example 자습서 또는 프로젝트의 홈 페이지 에서 더 많은 예제를 찾을 수 있습니다 .
답변
수영장은 이제 갈 길입니다.
const { Pool } = require('pg');
const pool = new Pool({
connectionString: DATABASE_URL,
ssl: false,
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
module.exports = {
query: (text, params) => pool.query(text, params)
}
그것은 다음과 같이 사용될 수 있습니다 db.query('<BEGIN,COMMIT,ROLLBACK,your query,anything')
답변
pg 풀을 전역 적으로 생성하고 db 작업을 수행해야 할 때마다 클라이언트를 사용한 다음 풀로 다시 릴리스하는 것이 좋습니다. 모든 db 작업이 완료되면 다음을 사용하여 풀을 종료하십시오.pool.end()
샘플 코드-
let pool = new pg.Pool(dbConfig);
pool.connect(function(err, client, done) {
if (err) {
console.error('Error connecting to pg server' + err.stack);
callback(err);
} else {
console.log('Connection established with pg db server');
client.query("select * from employee", (err, res) => {
if (err) {
console.error('Error executing query on pg db' + err.stack);
callback(err);
} else {
console.log('Got query results : ' + res.rows.length);
async.each(res.rows, function(empRecord) {
console.log(empRecord.name);
});
}
client.release();
});
}
});
자세한 내용은 내 블로그 게시물- 출처를 참조하세요.
답변
문서 에서 알 수 있듯이 두 옵션 모두 유효하므로 원하는 것을 선택하십시오. 당신으로서 나는 두 번째 선택을 할 것입니다.
답변
나는 이것에 대한 매우 간단한 핸들러에 관심이 있었기 때문에 복잡하게 만들지 않고 직접 만들었습니다. 나는 그것이 매우 기본적이라고 착각하지 않지만 일부 사람들이 시작하는 데 도움이 될 수 있습니다. 기본적으로 연결하고 쿼리를 실행하고 오류를 처리합니다.
function runQuery(queryString, callback) {
// connect to postgres database
pg.connect(postgresDatabase.url,function(err,client,done) {
// if error, stop here
if (err) {console.error(err); done(); callback(); return;}
// execute queryString
client.query(queryString,function(err,result) {
// if error, stop here
if (err) {console.error(err+'\nQuery: '+queryString); done(); callback(); return;}
// callback to close connection
done();
// callback with results
callback(result.rows);
});
});
}
그런 다음 다음과 같이 호출하여 사용할 수 있습니다.
runQuery("SELECT * FROM table", function(result) {
// Whatever you need to do with 'result'
}
답변
제가하는 방법은 “위의 모든 접근 방식”입니다.
Promise = require 'bluebird'
pg = module.exports = require 'pg'
Promise.promisifyAll pg.Client.prototype
Promise.promisifyAll pg.Client
Promise.promisifyAll pg.Connection.prototype
Promise.promisifyAll pg.Connection
Promise.promisifyAll pg.Query.prototype
Promise.promisifyAll pg.Query
Promise.promisifyAll pg
connectionString = process.env.DATABASE_URL
module.exports.queryAsync = (sql, values) ->
pg.connectAsync connectionString
.spread (connection, release) ->
connection.queryAsync sql, values
.then (result) ->
console.log result.rows[0]
.finally ->
release()