你认为的.NET数据库连接池,真的是全部吗?

发表于:2022-12-05 09:25

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:掘金码甲哥    来源:稀土掘金

#
Donet
#
DoNet
分享:
  一般我们的项目中会使用1到2个数据库连接配置,同程艺龙的数据库连接配置被收拢到统一的配置中心,由DBA统一配置和维护,业务方通过某个字符串配置拿到的是Connection对象。
  DBA能在对业务方无侵入的情况下,给业务方切换备份数据库,之后DBA要求旧连接池必须立即被清空, 那么问题来了: dotnet能不能立即清空连接池?, 注意我用得是清空,而不是释放连接。
  如果有同学不知道DBA做这个要求的目的,那我啰嗦一下:
  应用程序不再使用旧连接时,理论上你的连接池要被完全清空,因为单纯的释放连接,只会让连接池中的Connection处于Sleep状态,依旧维持了短时间的物理连接,这个短时间其实是不必要的占用,影响了旧连接数据库的吞吐量。
  前置知识背景
  回答这个问题之前, 我们还是先研究一下.NET数据库连接池。
  1. .NET数据库连接池的背景
  数据库连接是一个耗时的行为,大多数应用程序只使用1到几种数据库连接,为了最小化打开连接的成本,ado.net使用了一种称为连接池的优化技术
  2. .NET 数据库连接池的表现
  数据库连接池减少了必须打开新连接的次数,池程序维护了数据库物理连接。
  通过为每个特定的连接配置保持一组活动的连接对象来管理连接。
  每当应用程序尝试Open连接,池程序就会在池中找到可用的连接,如果有则返回给调用者;
  应用程序Close连接对象时,池程序将连接对象返回到池中(Sleep), 这个连接可以在下一次Open调用中重用。
  看黑板,下面是这次的重点:
  3. .NET是如何形成数据库连接池的?
  只有相同的连接配置才能被池化,.NET为不同的配置维护了不同的连接池。
  相同的配置限制为:
  ·进程相同;
  · 连接字符串相同;
  · 连接字符串关键key顺序相同。
  (同一连接提供的关键字顺序不同将被分到不同的池)。
  连接池中的可用连接的数量由连接字符串Max Pool Size决定。
  在一个应用程序中,有如下代码:
  using (SqlConnection connection = new SqlConnection(  
    "Integrated Security=SSPI;Initial Catalog=Northwind"))  
      {  
          connection.Open();
          // Pool A is created.  
      }  
    
  using (SqlConnection connection = new SqlConnection(  
    "Integrated Security=SSPI;Initial Catalog=pubs"))  
      {  
          connection.Open();
          // Pool B is created because the connection strings differ.  
      }  
    
  using (SqlConnection connection = new SqlConnection(  
    "Integrated Security=SSPI;Initial Catalog=Northwind"))  
      {  
          connection.Open();
          // The connection string matches pool A.  
      }  
  上面创建了三个Connection对象,但是只形成了两个数据库连接池。
  还是以上代码,如果有两个相同的应用程序,理论上就形成了四个数据库连接池。
  4. 连接池中的连接什么时候被移除?
  连接池中的连接空闲4-8 分钟,池程序会移除这个连接。
  应用程序下线,连接池直接被清空。
  .NET 如何清空连接池?
  有了以上知识背景。我们再来回顾一下 DBA的要求,切换原连接配置的时候,清空连接池。我从官方文档找到.NET提供了ClearAllPools、ClearPool静态方法用于清空连接池。
  ClearAllPools: 清空与这个DBProvider相关的所有连接池。
  ClearPool(DBConnection conn) 清空与这个连接对象相关的连接池。
  很明显,我们这次要使用ClearPool(DBConnection conn) 方法。
  光说不练不验证,不是我的风格。
  天锤压测/queryapi 产生一个包含大量连接对象的连接池;适当的时候,/clearpoolapi清空连接池。
   public class MySqlController : Controller
      {
          // GET: MySql
          [Route("query")]
          public string Index()
          {
              var s = "User ID=teinfra_neo_netreplay;Password=123456;DataBase=teinfra_neo_netreplay;Server=10.100.41.196;Port=3980;Min Pool Size=1;Max Pool Size=28;CharSet=utf8;";
              using (var conn = new MySqlConnection(s))
              {
                  var comm = conn.CreateCommand();
                  comm.CommandText = "select count(*) from usertest;";
                  conn.Open();
                  var ret = comm.ExecuteScalar();
                  comm.CommandText = "select count(*) from information_schema.PROCESSLIST WHERE HOST like  '10.22.12.245%';";
                  var len = comm.ExecuteScalar();
                  return $"查询结果:{ret} ,顺便查一下当前连接池的连接对象个数: {len}";
              };
          }
          [Route("clearpool")]
          public string Switch()
          {
              var s = "User ID=teinfra_neo_netreplay;Password=123456;DataBase=teinfra_neo_netreplay;Server=10.100.41.196;Port=3980;Min Pool Size=1;Max Pool Size=28;CharSet=utf8;";
              using (var conn = new MySqlConnection(s))
              {
                  conn.Open();
                  MySqlConnection.ClearPool(conn);
              };
              using (var conn = new MySqlConnection(s))
              {
                  conn.Open();
                  var comm = conn.CreateCommand();
                  comm.CommandText = "select count(*) from information_schema.PROCESSLIST WHERE HOST like  '10.22.12.245%';";
                  var len = comm.ExecuteScalar();
                  return $"之前已经清空连接池, 此次查询连接池有 {v1}  个连接对象";
              }
          }
      }
  1. 经过压测工具
  2. mysql数据库对比
  mysql的连接数查询命令, (host是web服务器IP):
  select * from information_schema.PROCESSLIST WHERE HOST like  '10.22.12.245%';
  3. 调用/clearpoolapi,清空连接池
  bingo,清空连接池的理论得到验证。
  干货旁白
  这是我在同程艺龙最近爬的比较深的坑位,
  我从本次实践中理解了.NET数据库连接池的定义方式、并配套掌握了DBProvider 对于.net连接数的查询定位方式。
  对祖传代码的改造,.NET数据获取组件SDK 确实提高了原数据库的吞吐量。
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号