连接池

连接池是可重用数据库连接的缓存。它允许使用少量数据库连接来服务许多 HTTP 请求。对 API 资源 的每个请求都会从池中借用一个连接来启动一个 事务

最小化连接对于性能至关重要。每个 PostgreSQL 连接都会创建一个进程,连接过多会导致可用资源耗尽。

动态连接池

为了节省系统资源,PostgREST 使用动态连接池。这使得池中的连接数量可以根据请求流量增加和减少。

  • 如果所有连接都被使用,则会添加一个新连接。池可以增长,直到达到 db-pool 大小。请注意,将其设置为高于数据库中 max_connections 设置是没有意义的。

  • 如果连接在一段时间内 (db-pool-max-idletime) 未使用,它将被释放。

  • 连接数据库时,使用 身份验证器 角色。您可以使用 db-uri 配置此角色。

连接应用程序名称

PostgREST 为其所有使用的连接设置连接 application_name。这对于 PostgreSQL 统计信息和日志很有用。

例如,您可以查询 pg_stat_activity 以获取 PostgREST 版本。

select distinct usename, application_name
from pg_stat_activity
where usename = 'authenticator';

   usename     |     application_name
---------------+--------------------------
 authenticator | PostgREST 12.1

连接生命周期

长期存在的 PostgreSQL 连接会消耗大量内存(有关更多详细信息,请参阅 此处)。在繁忙的系统中,db-pool-max-idletime 不会被达到,连接池可能会充满长期存在的连接。

为了避免此问题并节省资源,强制执行连接最大生命周期 (db-pool-max-lifetime)。达到最大生命周期后,池中的连接将被释放,并将创建新的连接。这不会影响正在运行的请求,只有未使用的连接才会被释放。

获取超时

如果池中所有可用的连接都处于繁忙状态,HTTP 请求将等待直到达到超时 (db-pool-acquisition-timeout)。

如果请求达到超时,它将被中止,并返回以下响应。

HTTP/1.1 504 Gateway Timeout

{"code":"PGRST003",
 "details":null,
 "hint":null,
 "message":"Timed out acquiring connection from connection pool."}

重要

收到此错误消息表明存在性能问题。要解决此问题,您可以

  • 减少查询执行时间。

    • 检查请求 执行计划 以调整您的查询,这通常意味着添加索引。

  • 减少请求数量。

    • 减少写入请求。执行 批量插入(或 Upsert)而不是逐行插入。

    • 减少读取请求。使用 资源嵌入。使用自定义数据库视图或函数将不相关的数据合并到单个请求中。

    • 使用 函数作为 RPC 将读取和写入逻辑合并到单个请求中。

  • 增加 db-pool 大小。

    • 这不是万能药,因为连接不能无限增长。在尝试此方法之前,请尝试前面的建议。

自动恢复

如果连接丢失,服务器将尝试重新连接到数据库。

  • 它将永远重试,并使用指数退避,重试之间的最大退避时间为 32 秒。这些尝试中的每一个都将被 记录

  • 只有当服务器认为错误是致命错误时,它才会停止重试。这可能是密码身份验证失败或内部错误。

  • 如果 db-channel-enabled 设置为 true(默认值),则重试将在连接丢失后立即发生。否则,它们将在请求到达后发生。

  • 为了确保有效状态,服务器在恢复时会重新加载 模式缓存配置

  • 为了通知客户端下一次重试,服务器会发送一个 503 Service Unavailable 状态,以及 Retry-After: x 标头。其中 x 是为下一次重试编程的秒数。

  • 可以通过将 db-pool-automatic-recovery 设置为 false 来禁用自动恢复。

使用外部连接池

可以使用外部连接池,例如 PgBouncer。会话池是兼容的,而事务池需要将 db-prepared-statements 设置为 false。语句池与 PostgREST 不兼容。

还要将 db-channel-enabled 设置为 false,因为 LISTEN 与事务池不兼容。虽然如果启用它应该不会出现任何错误。

注意

不建议使用外部连接池。 我们的基准测试 表明它提供的性能远低于 PostgREST 内置池。