30

使用DbContextPool提高EfCore查询性能

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzAwNTMxMzg1MA%3D%3D&%3Bmid=2654077165&%3Bidx=4&%3Bsn=d2b1473e973812b2caf0fc366b2ee1cd
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

nUBz2yQ.gif

长话短说

上个月公司上线了一个物联网数据科学项目,我主要负责前端接收设备Event,并提供 模型 参数下载(数据科学团队会优化参数)。 WebApp部署在Azure,模型参数使用Azure SQL Server存储。

最近从灰度测试转向全量部署之后,日志中时常出现: SQL Session会话超限的报错。

19/12/18 20:41:18 [Error].[Microsoft.EntityFrameworkCore.Query].[][0HLS3MS83SC3K:00000004].[http://******/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实例, 可以想象到

① 在高并发请求下,连接数不断累积,最终某时刻会超过 Azure 的连接限制数量。

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

EFCore2.0 为DbContext引入新的注册方式:透明地注册了 DbContext实例池:

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

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

- 默认的连接池数量为 128

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

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

这么重要的使用方式竟然不在 EFCore Doc指南中默认演示,真是一个坑。

myyYb2q.png!web

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

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

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;

YR3Ev2R.gif

总结

①  提示EFCore2.0新推出的DbContextPool特性,有效提高SQL查询吞吐量

②  尝试使用SQL Server 内置脚本自证会话中有效连接数

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

https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-2.0#dbcontext-pooling

b2Q7ryq.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK