从 Azure 函数调用 Azure SQL 数据库时出现暂时性错误

Getting transient errors when making calls against Azure SQL Database from Azure Function

我们正在使用 .NET Core 2.1 和 Entity Framework Core 2.1.1

我在 Azure 西欧有以下设置

多个 blob 上传到 Azure Blob 存储,Azure Functions(同时最多 5 个)通过 Azure 事件网格触发。 Azure Functions 根据存储在 Azure SQL 数据库中的元数据检查 blob 的结构。每个 blob 包含最多 500K 条记录和 5 列有效负载数据。对于每条记录,Azure Functions 都会调用 Azure SQL 数据库,因此没有缓存。

我经常遇到,当并行处理多个 blob(最多同时调用 5 个异步 Azure Functions),并且当 blob 大小大于 200K-500K 记录时,以下瞬态和连接错误来自.NET 核心 Entity Framework:

1。 已引发可能是由于暂时性故障导致的异常。考虑通过将 'EnableRetryOnFailure()' 添加到 'UseSqlServer' 调用来启用瞬态错误弹性。

2。 已成功与服务器建立连接,但在登录前握手期间发生错误。 (提供商:SSL 提供商,错误:0 - 等待操作超时。)

3。 连接超时已过期。尝试使用登录前握手确认时超时期限已过。这可能是因为登录前握手失败或服务器无法及时响应。尝试连接到路由目标时发生此故障。尝试连接到原始服务器时花费的时间是 - [Pre-Login] initialization=13633;握手=535; [登录]初始化=1;认证=0; [Post-登录]完成=156;尝试连接到此服务器时花费的时间是 - [登录前] 初始化 = 5679;握手=2044;

4。 已成功与服务器建立连接,但在登录前握手期间发生错误。 (提供商:SSL 提供商,错误:0 - 等待操作超时。)

  1. 服务器提供路由信息,但超时已过。

同时在测试期间报告了 Azure SQL 数据库的 any/no 健康事件,指标看起来很棒:MAX Workers < 3.5%,Sum Successful Connections < 35,最大会话百分比 < 0.045%,最大日志 UI 百分比 < 0.024%,失败连接总和 = 0,最大 DTU < 10%,最大数据 IO < 0.055%,最大 CPU < 10%.

运行 Azure SQL 数据库 (sys.database_connection_stats_ex) 上的连接统计信息:没有失败、中止或受限的连接。

select *
from sys.database_connection_stats_ex
where start_time >= CAST(FLOOR(CAST(getdate() AS float)) AS DATETIME)
order by start_time desc

有没有人在与 .Net Core Entity Framework 和 Azure SQL 数据库结合时遇到过类似的问题。为什么我会收到这些暂时性错误,为什么 Azure SQL 数据库指标看起来很好但根本没有反映出存在问题?

非常感谢您的帮助。

using Microsoft.EntityFrameworkCore;

namespace MyProject.Domain.Data
{
    public sealed class ApplicationDbContextFactory : IApplicationDbContextFactory
    {
        private readonly IConfigurationDbConfiguration _configuration;
        private readonly IDateTimeService _dateTimeService;

        public ApplicationDbContextFactory(IConfigurationDbConfiguration configuration, IDateTimeService dateTimeService)
        {
            _configuration = configuration;
            _dateTimeService = dateTimeService;
        }

        public ApplicationDbContext Create()
        {
            //Not initialized in ctor due to unit testing static functions.
            var options = new DbContextOptionsBuilder<ApplicationDbContext>()
                .UseSqlServer(_configuration.ConfigurationDbConnectionString).Options;

            return new ApplicationDbContext(options, _dateTimeService);
        }
    }
}

我找到了关于 sql 数据库瞬态错误的优秀文档:

来自文档:

A transient error has an underlying cause that soon resolves itself. An occasional cause of transient errors is when the Azure system quickly shifts hardware resources to better load-balance various workloads. Most of these reconfiguration events finish in less than 60 seconds. During this reconfiguration time span, you might have connectivity issues to SQL Database. Applications that connect to SQL Database should be built to expect these transient errors. To handle them, implement retry logic in their code instead of surfacing them to users as application errors.

然后详细说明了如何为暂时性错误构建重试逻辑。

Entity Framework 和 SQL 服务器实现重试逻辑:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseSqlServer("<connection string>", options => options.EnableRetryOnFailure());
}

您可以在此处找到更多信息:

删除并重新创建数据库用户,并确保填写用户名正下方的登录名框。这也将解决旧 SQL 版本上的相同问题。