使用Azure AD托管身份连接Azure SQL时的性能问题排查
问题描述
我将项目部署为Azure上的Azure Functions,对比两种连接Azure SQL Database的连接字符串类型的性能:
- 标准类型:
Server=tcp:myserver.database.windows.net,1433;Initial Catalog=myDataBase;Persist Security Info=False;UserID=mylogin@myserver;Password=myPassword;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False; - Azure AD身份类型:
Server=tcp:myserver.database.windows.net; Authentication=Active Directory Managed Identity; Database=myDataBase; Column Encryption Setting=enabled
部分场景下,第二种类型的数据库连接耗时超10秒,而同一时段第一种类型最多仅需2秒。我想明确:这是否与Azure AD身份令牌获取耗时较长有关?同时希望定位数据库连接缓慢的原因。
我怀疑的代码片段如下:
// Initialize AzureKeyVault provider SqlColumnEncryptionAzureKeyVaultProvider azureKeyVaultProvider = new(new DefaultAzureCredential()); // Register AzureKeyVault provider SqlConnection.RegisterColumnEncryptionKeyStoreProviders( customProviders: new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>( capacity: 1, comparer: StringComparer.OrdinalIgnoreCase) { { SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, azureKeyVaultProvider} });
分析与解答
1. Azure AD令牌获取确实可能是耗时因素之一
使用托管身份连接时,每次建立连接都需要从Azure AD获取访问SQL Database的令牌。如果函数实例冷启动、网络延迟高,或者Azure AD令牌服务存在临时波动,都会导致令牌获取耗时增加,进而拉长整体连接时间。而标准连接字符串用固定账号密码,无需额外的令牌请求步骤,这部分开销自然不存在。
2. 列加密配置带来的Key Vault交互成本是更关键的因素
你的代码中注册了SqlColumnEncryptionAzureKeyVaultProvider,且连接字符串开启了Column Encryption Setting=enabled,这意味着每次建立连接时,SQL驱动需要:
- 从Azure Key Vault获取列加密密钥(CEK)
- 验证密钥的有效性并完成解密初始化
这些操作涉及额外的网络请求到Key Vault,尤其是在函数冷启动、Key Vault与SQL Database区域不同步,或者密钥权限配置存在隐性延迟时,会大幅增加连接耗时。而标准连接字符串没有开启列加密,完全跳过了这部分流程,所以速度更快。
3. 代码注册时机的问题
如果这段注册代码是在每次函数触发时执行(而非在函数启动时全局注册),会导致重复初始化SqlColumnEncryptionAzureKeyVaultProvider和重复注册,额外增加不必要的开销。
优化建议
- 全局注册密钥存储提供者:将
SqlConnection.RegisterColumnEncryptionKeyStoreProviders移到Azure Functions的启动类(如Startup.cs或Program.cs的初始化逻辑中),只执行一次,避免重复初始化。 - 缓存Azure AD令牌:
DefaultAzureCredential默认会缓存令牌,确保函数运行环境的缓存机制正常工作,减少重复请求Azure AD的次数。 - 检查资源区域一致性:尽量让Key Vault、Azure Functions、SQL Database处于同一区域,降低网络延迟。
- 排查Key Vault状态:确认托管身份对Key Vault的密钥操作权限配置正确,查看Key Vault的监控指标(如请求延迟、成功率),排查是否存在服务端瓶颈。
- 拆分耗时监控:在代码中添加日志,分别记录令牌获取、Key Vault密钥获取、SQL连接建立各阶段的耗时,精准定位拖慢整体速度的环节。
内容的提问来源于stack exchange,提问作者simpleman9x
相关产品推荐
相关产品推荐

