使用用户指定的托管标识连接池连接 Azure SQL 数据库

5
似乎EF Core连接池在使用用户分配的托管标识时无法正常工作。我的网页从Angular前端向Web API控制器发出3个Ajax调用。该控制器使用包含实现IDisposable的DbContext的存储库类。
我们正在运行.NET Core 3.1,使用默认依赖项容器和默认的DbContext设置,因此它是ServiceLifeTime.Scoped。
我的DbContext构造函数中有如下代码来处理托管标识。
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://learn.microsoft.com/zh-cn/azure/azure-sql/database/resource-limits-dtu-single-databases#standard-service-tier

当我切换为带有用户ID和密码的标准SQL Server身份验证时,它按预期工作。

在使用托管标识时,我需要关闭连接池吗?那似乎可以解决问题,但我确定关闭连接池后连接需要更长时间建立。

-Randy


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

2
如果您在每个请求上创建一个新的DBContext,并且它在构造函数中调用了credential.GetToken(...),则很可能每次都会得到不同的令牌,因此连接无法汇集。将令牌检索和存储移出构造函数应该可以解决这个问题。

谢谢mpeterson!那基本上就是关键。我必须使用一个单例服务来获取令牌,并将其注入到dbContext ctor中。 - randy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接