zoukankan      html  css  js  c++  java
  • EF2.0新特性DbContext Pooling

    长话短说

      上个月公司上线了一个物联网数据科学项目,我主要负责前端接受物联网事件,并提供 参数下载。

    webapp 部署在Azure云上,参数使用Azure SQL Server存储。 最近从灰度测试转向全量部署之后,日志时常收到:

     SQL Session超限报错。

    19/12/18 20:41:18 [Error].[Microsoft.EntityFrameworkCore.Query].[][0HLS3MS83SC3K:00000004].[http://localhost/api/v1/soc-prediction-model/all].[].[GetModeParameters] 
    An exception occurred while iterating over the results of a query for context type 'Gridsum.SaicEnergyTracker.CarModelContext'.
    Microsoft.Data.SqlClient.SqlException (0x80131904): Resource ID : 2. The session limit for the database is 300 and has been reached. See 'http://go.microsoft.com/fwlink/?LinkId=267637' for assistance.
    Changed database context to 'saic-carmodel'.
    Changed language setting to us_english.
       at Microsoft.Data.ProviderBase.DbConnectionPool.CheckPoolBlockingPeriod(Exception e)
       at Microsoft.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
       at Microsoft.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
       at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
       at Microsoft.Data.ProviderBase.DbConnectionPool.WaitForPendingOpen()
    --- End of stack trace from previous location where exception was thrown ---
       at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnectionAsync(Boolean errorsExpected, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnectionAsync(Boolean errorsExpected, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
       at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.AsyncQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()

     排查

      我在Azure上使用的是 SQL Server Basic Edition(好歹也是付费版),全量发布至今,日均SQL访问次数约为10000,查询了Azure SQL的使用限制文档

    一句话: 付费级别和计算资源大小决定了  Azure SQL最大会话数和请求数。要缓解,要么升级硬件资源,要么优化查询利用率。

    查看使用EFCore访问SQL Server的过程,  也是官方默认用法:

    •  在依赖注入框架 注册一个自定义的 DbContext类型
    • 在 Controller 构造函数中获取 DbContext实例

    这意味着每次请求都会创建一个DbContext实例, 可以想象到

     主: 频繁创建和销毁DbContext 实例,影响App Service自身性能。

     次:  在急缺CPU资源下,连接会话来不及释放,会话数不断累积,最终某时刻会超过Azure的会话限制数。

    EFCore2.0 为DbContext引入新的注册方式, 能够透明的注册一个 DbContext实例池:

    services.AddDbContextPool<CarModelContext>(options => options.UseSqlServer(Configuration.GetConnectionString("SQL")));

       - 一如既往支持lambda方式注册连接字符串

      - 默认的DbContext Pool实例数量为 128

      - 每次使用完DbContext不会释放对象,而是重置并回收到DBContextPool

    Web程序中通过重用池中DbContext实例可增加高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点,   这也是EFCore2.0 其中一个性能亮点。

    这么重要的使用方式竟然不在 Microsoft doc 默认Demo中推荐使用,真是一个坑。

    修改代码重新部署之后,历经几天测试,暂时未出现最开始的SqlException异常。

    验证

    回过头随机验证SQL Server 有连接的会话数:

    SELECT DEC.session_id, DEC.protocol_type, DEC.auth_scheme,
      DES.login_name, DES.login_time
    FROM sys.dm_exec_sessions AS DES
      JOIN sys.dm_exec_connections AS DEC
        ON DEC.session_id = DES.session_id;

    总结

    ①  提示EFCore2.0 新推出的DbContextPool 特性, 提高App Service 性能。

    ②  尝试使用SQL Server 内置脚本验证当前有效连接的 会话数

    --------------------------------------20191222 更新------------------------

     查阅资料, DbContext 确实是EFCore连接会话的概念,EFCore2.0推出的DbContextPool 通过减少DBContext频繁实例化、销毁的成本来提高程序性能,

    概念上类似 Ado.Net原生的连接池的概念(Ado.NET连接池是更重更底层的资源, 效果会更好)。

    至于SQL查询吞吐量,DbContextPool 并没有很直接的证据能证明对SQL吞吐量有改善,目前的证据显示DbContextPool 因为app 性能提升,前端处理请求的吞吐量有20% 提升。

    鉴于没有实际证据证明对SQL查询吞吐量有改善,本文不再将 数据库底层的改善直接归功于使用DbContextPool, 因此本文删除了上面的关联关系,但是DbContextPool 还是应该作为默认实践。

     + https://github.com/aspnet/EntityFrameworkCore/issues/9426

    https://github.com/aspnet/EntityFrameworkCore/issues/10125

    +  https://stackoverflow.com/questions/48443567/adddbcontext-or-adddbcontextpool

    https://www.mssqltips.com/sqlservertip/5507/understanding-and-using-sysdmexecsessions-in-sql-server/

  • 相关阅读:
    Gitlab_ansible_jenkins三剑客⑥Jenkins和ansible集成
    Gitlab_ansible_jenkins三剑客⑤jenkins Pipeline-job的使用
    Gitlab_ansible_jenkins三剑客④jenkins安装图解及freestyle的简单使用
    Gitlab_ansible_jenkins三剑客③Ansible的安装及使用
    Gitlab_ansible_jenkins三剑客②Gitlab的后台管理
    Gitlab_ansible_jenkins三剑客①搭建gitlab的详细步骤
    windows2012服务器中安装php7+mysql5.7+apache2.4环境
    07binlog日志介绍
    open()系统调用的实现
    文件系统中的目录查找
  • 原文地址:https://www.cnblogs.com/JulianHuang/p/12074483.html
Copyright © 2011-2022 走看看