Postgresql 和 .Net - 具有多个端点的连接池

Bri*_*n S 6 c# postgresql npgsql

基本介绍:

连接字符串: Host=IP;Port=somePort;Username=someUser;Password=somePass;Database=someDb;Maximum Pool Size=100

我的 Web 应用程序有几十个可通过 WS 和 HTTP 使用的端点。这些端点中的每一个都打开一个新的 NPGSQL 连接(都使用与上面相同的连接字符串),处理数据,然后通过using语句关闭。

问题: 当应用程序重新启动以进行更新时,通常有 2-3,000 个用户全部重新连接。这通常会导致有关连接池已满和新连接因已经有太多客户端而被拒绝的错误。但是,一旦它最终可以上线,它通常在任何给定时间只使用 5-10 个连接。

问题: 下面的逻辑是使用连接池的正确方法吗?每个端点都使用相同的连接字符串创建一个新的 NPGSQL 连接,指定连接池为 100?

似乎连接池经常会达到 100,但这些连接中有大约 80/100 在数据库查看器中显示为空闲,新连接请求由于池溢出而被拒绝。

更好的选择? 我也可以尝试通过慢慢地允许新用户重新连接来强制更“优雅”的启动,但我不确定与每个端点创建新连接的逻辑是否正确。

// DB Connection String - Used for all NPGSQL connections
const string connectionStr "Host=IP;Port=somePort;Username=someUser;Password=somePass;Database=someDb;Maximum Pool Size=100";

// Endpoint 1 available via Websocket
public async Task someRequest(someClass someArg)
{
    /* Create a new SQL connection for this user's request using the same global connections string */
    using var conn = new NpgsqlConnection(connectionStr);
    conn.Open();

    /* Call functions and pass this SQL connection for any queries to process this user request */
    somefunction(conn, someArg);
    anotherFunction(conn, someArg);

    /* Request processing is done */
    /* conn is closed automatically by the "using" statement above */
}

// Endpoint 2 available via Websocket
public async Task someOtherRequest(someClass someArg)
{
    /* Create a new SQL connection for this user's request using the same global connections string */
    using var conn = new NpgsqlConnection(connectionStr);
    conn.Open();

    /* Call functions and pass this SQL connection for any queries to process this user request */
    somefunction(conn, someArg);
    anotherFunction(conn, someArg);

    /* Request processing is done */
    /* conn is closed automatically by the "using" statement above */
}

// endpoint3();
// endpoint4();
// endpoint5();
// endpoint6();
// etc.
Run Code Online (Sandbox Code Playgroud)

编辑: 我已经提出了更改建议,方法是在处理过程中关闭连接并将它们发送回池。但是,启动时问题仍然存在。

  1. 应用程序启动 - 已声明 100 个连接用于池化。几乎所有人都闲着。应用程序收到连接池耗尽错误,甚至几乎没有处理任何事务。

  2. 交易突然开始搅动,不知道为什么?这是在某种超时之后吗?我知道在某个地方的文档中有某种 300 秒的默认超时......这可能与此处匹配。

  3. 事务再次锁定,池耗尽错误恢复。

  4. 交易激增并恢复,用户请求再次开始。

  5. 应用程序正常水平。

在此处输入图片说明

编辑 2: 这个启动问题似乎总是从启动开始需要 5 分钟才能清除空闲事务的死锁并开始运行所有查询。

我知道 5 分钟是idle_in_transaction_session_timeout. 但是,这次我尝试运行SET SESSION idle_in_transaction_session_timeout = '30s';10s在启动期间,它似乎根本没有影响它。

我不知道为什么这 100 个池连接会像启动时那样闲置,需要 5 分钟来清除并允许查询在这种情况下运行......

Bri*_*n S 2

我忘记用一些最新信息更新这篇文章。我在代码中还进行了一些其他内部优化。

其中主要的一个,就是简单地更改conn.Open();await conn.OpenAsync();和。conn.Close();conn.CloseAsync();

我拥有的其他一切都是正确异步的,但 NPGSQL 中的所有新连接仍然存在 IO 阻塞,导致大突发时性能更差。

这是一个非常明显的变化,但我什至没有想到寻找用于打开和关闭连接的异步方法。