kubernetes Nodejs应用程序使用“node postgres”,在GKE中每60分钟出现一次“连接意外终止”

jhdbpxl9  于 2023-01-12  发布在  Kubernetes
关注(0)|答案(2)|浏览(159)

我有多个使用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)

下面是我如何将我的客户端连接到数据库:
Database.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引擎中将每个应用程序作为微服务运行。K8s中是否存在任何可能导致每小时连接丢失的配置?(即使客户端空闲或不空闲,也会发生此错误)

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()。下面是我为什么应该使用pool而不是client的解释:https://stackoverflow.com/a/48751665/12052533

nfs0ujit

nfs0ujit1#

我发现了问题:
在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;
            })
    }
8ljdwjyq

8ljdwjyq2#

我在你的代码中看到的错误是,你没有关闭连接后,使client.connect().每当我们连接一个客户端或池,这意味着我们所有的请求将抛出该连接,但如果你不打算关闭它使用后,它将继续堆积,因为在一段时间后,你的数据库连接将崩溃!
因此,根据我的最佳实践,对于1-2个查询,在它打开和自动关闭连接时使用pool.query(),我们不必手动执行它。
或者当在单个API中使用大量sql查询时,使用const client = pool.connect(),然后使用client.query(),通过client.release()关闭连接;

相关问题