具有用户分配的托管标识的 Azure SQL 数据库连接池

Posted

技术标签:

【中文标题】具有用户分配的托管标识的 Azure SQL 数据库连接池【英文标题】:Azure SQL Database Connection Pooling with User Assigned Managed Identity 【发布时间】:2021-07-26 19:28:29 【问题描述】:

似乎 EF Core 连接池无法与用户分配的托管标识一起正常工作。我的网页从我的 Angular 前端对 Web API 控制器进行了 3 次 Ajax 调用。控制器使用包含实现IDisposableDbContext 的存储库类。

我们使用默认的依赖容器和默认的DbContext 设置运行带有EF Core 的.NET Core 3.1,所以它是ServiceLifeTime.Scoped

我的 DbContext ctor 有类似这样的托管身份代码。

var connection = (Microsoft.Data.SqlClient.SqlConnection)Database.GetDbConnection();

var options = new DefaultAzureCredentialOptions  ManagedIdentityClientId = surveyToolOptions.Value.ManagedIdentityClientId ;
var credential = new DefaultAzureCredential(options);
var token = credential.GetToken(new Azure.Core.TokenRequestContext(new[]  "https://database.windows.net/.default" ));

connection.AccessToken = token.Token;

当我查看会话计数时,每次我点击页面时它都会增加 3 个连接。它从不重用连接。它们也不会消失大约 4-5 分钟。

SELECT host_name, Program_name, COUNT(*) 
FROM sys.dm_exec_sessions  s
JOIN sys.databases AS d ON s.database_id = d.database_id
GROUP BY host_name, Program_name

这是一个问题,因为 Azure SQL 数据库的会话数非常有限。 https://docs.microsoft.com/en-us/azure/azure-sql/database/resource-limits-dtu-single-databases#standard-service-tier

当我使用用户 ID 和密码将其切换到标准 SQL Server 身份验证时,它按预期工作。

使用托管身份时是否需要关闭连接池?这似乎确实有效,但我确信建立与池关闭的连接需要更长的时间。

-兰迪

【问题讨论】:

每个不同的安全上下文都是一个单独的连接池。如果您使用服务帐户而不是最终客户端身份对数据库进行身份验证,您将获得更好的可扩展性。 @DanGuzman,我认为用户分配的托管身份是服务帐户,还是您说我应该使用系统分配的托管身份?在任何一种情况下,它都不应该与最终用户有任何关系,至少我是这么认为的。 我误解了您使用的凭据。我认为@mpeterson 的回答应该解决池化问题。 【参考方案1】:

如果您在每个请求上都创建一个新的DBContext,并且它在构造函数中调用credential.GetToken(...),那么您很可能每次都得到不同的令牌,因此无法合并连接。

在构造函数之外检索和存储令牌应该可以解决这个问题。

【讨论】:

感谢 mpeterson!这本质上是关键。我必须使用获取令牌并注入 dbContext ctor 的单例服务。

以上是关于具有用户分配的托管标识的 Azure SQL 数据库连接池的主要内容,如果未能解决你的问题,请参考以下文章

如果用户是用户分配托管标识,则确定 Azure SQL Server 中的用户名

使用自动化帐户中用户分配的托管标识连接到 Azure 存储帐户(使用 Azure RM 模块)

系统分配的托管标识的 Azure ARM 角色分配第一次运行失败

如何使用用户分配的托管标识访问 Azure 中 Function App Config 的 Key Vault

如何获取Azure App Service的特定用户分配的托管服务标识的令牌?

可以将系统分配的托管服务标识添加到 AAD 组吗?