Alex Liang

pg-pool 解決 Connection terminated unexpectedly

前陣子公司內部負責處理 data pipeline 的服務偶爾發生 PostgreSQL Connection terminated unexpectedly,造成服務 crash 並中斷 pipeline。

這篇文章記如何解決問題。

在 Connection pool 初始化時,監聽 connect 事件並加入 error handler

1
2
3
4
5
6
7
8
9
10
11
12
import { Pool } from "pg";

const pool = new Pool({
// PG config
});

// 加入 connect error handler
pool.on("connect", (client) => {
client.on("error", (err) => {
console.info(`connection error: ${err}`);
});
});

現代的 infra 通常會在 PostgreSQL 前多加 pgBouncer 當 proxy,它也具備 connection pool 功能。
上述的程式碼是 application layer 的 connection pool,在多層的架構下,會發生 application 以為手上的 connection 還是連著的,但實際上已被 pgBouncer 斷掉。
我們可以在取得 connection 時檢查連線是否建立,例如:

1
2
3
4
5
6
7
8
9
async getConnection() {
const connect = await pool.connect();
const checkResult = await client.query("SELECT 1");
if (!checkResult || checkResult.rows.length === 0) {
// wait for 1 second
await new Promise(resolve => setTimeout(resolve, 1000));
}
return await pool.connect();
}

透過以上方法,能讓 application 在操作