在ASP.NET Core 3.1中以正确的方式使用多个connectionString进行DI NpgsqlConnection postgreSQL。

19 浏览
0 Comments

在ASP.NET Core 3.1中以正确的方式使用多个connectionString进行DI NpgsqlConnection postgreSQL。

我正在努力在ASP.NET Core 3.1中注册具有多个连接字符串的DI NpgsqlConnection(),Dapper v2.0.78和Postgres v11。我将提供当前状态并修复下面的代码:\n

当前状态

\n

这个想法来自这里

\n步骤1Startup.cs --> ConfigureServices()\n

services.AddTransient(sp =>
{
  var connectionDict = new Dictionary
  {
     { DatabaseConnectionName.Cnn1, "连接字符串1"},
     { DatabaseConnectionName.Cnn2, "连接字符串2"}
  };
  return new DapperDbConnectionFactory(connectionDict);
});

\n步骤2DapperDbConnectionFactory如下所示:\n

public class DapperDbConnectionFactory : IDbConnectionFactory
{
    private readonly IDictionary _connectionDict;
    public DapperDbConnectionFactory(IDictionary connectionDict)
    {
        _connectionDict = connectionDict;
    }
    public IDbConnection CreateDbConnection(DatabaseConnectionName connectionName)
    {
        string connectionString = null;
        if (_connectionDict.TryGetValue(connectionName, out connectionString))
        {
            return new NpgsqlConnection(connectionString); // <--- 我认为问题出在这里
        }
        throw new ArgumentNullException();
    }
}

\n步骤3:我使用这段代码的方式:\n

public ConstructorMedthod(IDbConnectionFactory _connFactory)
{
   _conn = _connFactory.CreateDbConnection(DatabaseConnectionName.Cnn1);
}
public async Task> Handle(...)
{
 ...
   var query = await _conn.QueryMultipleAsync("这里是查询内容"); // <--- 我认为问题出在这里
 ...
}

\n我确实认为使用方式不正确,需要至少将调用_conn.QueryMultipleAsync的代码包装在using语句中,以确保连接关闭和释放,然后返回连接池。因为DI容器只管理DapperDbConnectionFactory的生命周期,而不是IDbConnection的生命周期。\n结果有时会出现以下错误:\n

\nNpgsql.NpgsqlException (0x80004005):连接池已耗尽,请提高MaxPoolSize(当前为100)或Timeout(当前为15秒)\n

\n我不得不重新启动应用程序,然后它就恢复正常了。所以我不确定问题是因为最大连接池还是由于网络超时。应该能够检查池中的连接数与该时刻的最大连接池进行对比。我假设是这样的。\n

修复代码

\n我有两个想法:\n

    \n

  1. 将调用_conn.QueryMultipleAsync的代码包装在using语句中。但是这种方式需要在调用_conn的所有代码中进行太多的更改。
  2. \n

  3. 改变DI的方式(这个想法来自这里)。更多细节如下。
  4. \n

\n步骤1Startup.cs --> ConfigureServices()\n

services.AddTransient(serviceProvider => cnn_Name =>
{
    switch (cnn_Name)
    {
        case "Cnn1":
            return new NpgsqlConnection("连接字符串1");
        case "Cnn2":
            return new NpgsqlConnection("连接字符串2");
        default:
            throw new KeyNotFoundException();
    }
});
public delegate IDbConnection ServiceResolver(string connectionstring);

\n步骤2:我使用的方式:\n

private readonly IDbConnection _conn;
public ConstructorMedthod(ServiceResolver serviceAccessor)
{
   _conn = serviceAccessor(DbConnectionKey.Cnn1);
}
public async Task> Handle(...)
{
 ...
   var query = await _conn.QueryMultipleAsync("这里是查询内容"); 
   // 现在我假设_DI容器将关闭和释放_conn。
 ...
}

\n

问题

\n

    \n

  1. 在ASP.NET Core 3.1中,如何正确注册具有多个连接字符串的DI NpgsqlConnection和postgreSQL?
  2. \n

  3. 我如何验证连接字符串是否返回到连接池,类似于在PostgreSQL上进行查询,例如这个这个
  4. \n

\n

SELECT * FROM pg_stat_activity;

\n

    \n

  1. 如何将最大连接池增加到大于100。是否是最佳实践?我在这篇帖子中发现说
  2. \n

\n

\n仅增加max_connections是一个坏主意。您还需要增加shared_bufferskernel.shmmax。\n

\n但实际上,我使用的是AWS的RDS PostgreSQL。所以我在考虑像这样配置appsettings。\n

\nUserID=root;Password=myPassword;Host=localhost;Port=5432;Database=myDataBase;Pooling=true;Minimum\nPool Size=0;Maximum Pool Size=200;\n

\n此外,正如这篇帖子所说\n

\nNpgsql连接池是在您的应用程序进程内实现的 - 它与PostgreSQL完全无关。\n

\n所以我对于PostgreSQL中的最大连接池(问题#2)和Appsettings(问题#3)之间的理解非常困惑。

0
0 Comments

问题的出现的原因是作者在处理多个连接字符串时,不确定自己是否正确地使用了最佳实践。在详细阅读了评论后,发现必须像下面这样使用`using`语句:

public async Task> Handle(...)
{
 ...
     using(var conn = _connFactory.CreateDbConnection(DatabaseConnectionName.Cnn1))
     {
       var response = await conn.QueryMultipleAsync("Query content here");
     }
 ...
}

否则,会出现以下错误:

Npgsql.NpgsqlException (0x80004005): The connection pool has been

exhausted, either raise MaxPoolSize (currently 100) or Timeout

(currently 15 seconds)

或者

"53300: remaining connection slots are reserved for non-replication

superuser connections"

希望这条突出显示的评论能帮助大家避免隐藏的错误。

更新 - 2022-05-13

从Rojansky的答案中,我们已经澄清了关于`Appsetings -> Maximum Pool Size=200;`和`PostgreSQL --> SHOW max_connections;`之间的混淆 - 问题#3。

[原文链接](https://stackoverflow.com/questions/44272459#comment127407163_44272654)

![enter image description here](https://i.stack.imgur.com/xLHwg.png)

0