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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM