【问题标题】:Nodejs application using "node postgres" having a "Connection terminated unexpectedly" every 60min in GKE使用“node postgres”的 Nodejs 应用程序在 GKE 中每 60 分钟出现一次“连接意外终止”
【发布时间】:2021-10-10 12:05:51
【问题描述】:

我有多个使用 Node.js 和 pg (node-postgres) 运行的应用程序。

我遇到的问题是每个应用程序每小时都会收到错误“连接意外终止”。这是错误:

> node ./dist/app.js

App Started
events.js:174
      throw er; // Unhandled 'error' event
      ^

Error: Connection terminated unexpectedly
    at Connection.con.once (/app/node_modules/pg/lib/client.js:255:9)
    at Object.onceWrapper (events.js:286:20)
    at Connection.emit (events.js:198:13)
    at Socket.<anonymous> (/app/node_modules/pg/lib/connection.js:139:10)
    at Socket.emit (events.js:203:15)
    at endReadableNT (_stream_readable.js:1145:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)
Emitted 'error' event at:
    at connectedErrorHandler (/app/node_modules/pg/lib/client.js:202:10)
    at Connection.con.once (/app/node_modules/pg/lib/client.js:272:9)
    at Object.onceWrapper (events.js:286:20)
    [... lines matching original stack trace ...]
    at process._tickCallback (internal/process/next_tick.js:63:19)

这是我将客户端连接到数据库的方法:

数据库.ts:

import { Client, QueryResult } from 'pg';

export default class DatabaseModule {

    private client: Client;

    constructor() {
        this.client = new Client({
            connectionString: process.env.DATABASE_URL
        });
    }

    public init(): Promise<any> {
        return this.client.connect();
    }
}

app.ts:

Promise.all([
    express.init(),
    database.init()
])
.then(() => {
    console.log("App Started");
    [load routes...];
})
.catch((error) => {
    console.error(error);
    process.exit(1);
});

在本地一切正常,但在生产环境中不行。

在生产环境中,我们将每个应用都作为微服务运行在 Google Kubernetes Engine 中。 K8s 中是否有任何配置可能导致每小时连接丢失? (即使Client空闲或不空闲,也会出现这个错误)

NAME                                                    READY   STATUS    RESTARTS   AGE
my-service-57c9f99767-wnm47                             2/2     Running   96         4d

如您所见,我的应用有 96 次重新启动:4 天 * 24 小时 = 96 => 每小时错误导致 pod 崩溃。

我们使用的是由 Google Cloud SQL 托管的 postgreSQL 服务器,K8s 中的每个应用都可以通过本地地址访问它。

编辑:

我刚刚在 Google Cloud SQL 文档中找到了这个: WebSockets are always available to your application without any additional setup. Once a WebSockets connection is established, it will time out after one hour.

所以错误是由于使用 pg.Client 与 SQL 服务器的持久连接而产生的。我将尝试使用 pg.Pool()。 这是我为什么应该使用池而不是客户端的解释:https://stackoverflow.com/a/48751665/12052533

【问题讨论】:

  • 您是否尝试过将connectionTimeoutMillis 明确设置为喜欢几天或几周?这是我看到的唯一相关选项。您可以将选项传递给客户端构造函数。
  • connectionTimeoutMillis?: number, // number of milliseconds to wait for connection, default is no timeout:现在是等待我的应用连接的时间吗?因为它最初确实连接到数据库,然后在 60 分钟后断开连接......而且如您所见,默认为无超时。
  • 在数据库服务器的日志文件中查找相应的错误消息。
  • @mmoussa,如果您找到解决方案(或至少是解释),您应该将其发布为您问题的答案,而不是编辑。对其他人来说会更清楚。

标签: node.js postgresql kubernetes google-kubernetes-engine node-postgres


【解决方案1】:

我发现了问题:

在 Google Cloud SQL 文档中:WebSockets are always available to your application without any additional setup. Once a WebSockets connection is established, it will time out after one hour.

错误是由使用 pg.Client() 产生的,因为我有一个持久连接到我的数据库,这是一个不好的做法。客户端应连接到数据库,然后在执行完查询后结束其连接。

我将使用 pg.Pool(),因为它会生成客户端,并且更适合多个请求。 生成客户端后,我只需释放所有客户端。

我删除了 database.init() 并修改了 database.query() 函数,如下所示:

     public query(command: string, args?: Array<any>): Promise<QueryResult> {
        if (args === undefined)
            args = [];
        return this.pool.connect()
            .then((client: Client) => {
                return this.queryClient(client, command, args)
            })
            .then((result: QueryResult) => {
                return result;
            })
            .catch((error) => {
                throw error;
            });
    }

     private queryClient(client: Client, command: string, args?: Array<any>): Promise<QueryResult> {
        return client.query(command, args)
            .then((result: QueryResult) => {
                client.release();
                return result;
            }).catch((error) => {
                client.release();
                throw error;
            })
    }

【讨论】:

    猜你喜欢
    • 2018-09-16
    • 2022-12-14
    • 2020-05-10
    • 1970-01-01
    • 2022-10-07
    • 2016-09-07
    • 2018-06-06
    • 2011-04-25
    • 1970-01-01
    相关资源
    最近更新 更多