仅在某些实例上出现 Azure WebJob DB 连接错误

Azure WebJob DB Connection Error Only on some instances

我有两个 Azure WebJobs。第一个接受传入消息,告诉它获取 PDF 并将其分解为单独的页面图像,然后将另一条消息排队等待第二个 WebJob 处理单独的页面。它在我们的 QC 实例上运行良好,但当我们尝试转移到生产环境时,我开始在第二份工作中遇到 st运行ge 错误,但并不一致。第一项工作 运行s 并将文件分成页面图像。那工作正常。我已经确认每个页面图像都已创建并且每个页面消息都已排队。但是,对于第二个作业,只有部分消息得到正确处理。其余在 WebJob 诊断中显示此错误:

Microsoft.Azure.WebJobs.Host.FunctionInvocationException: Microsoft.Azure.WebJobs.Host.FunctionInvocationException: Exception while executing function: Functions.ProcessBatchPage ---> System.Data.SqlClient.SqlException: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 52 - Unable to locate a Local Database Runtime installation. Verify that SQL Server Express is properly installed and that the Local Database Runtime feature is enabled.) ---> System.ComponentModel.Win32Exception: The system cannot find the file specified

但奇怪的是,这个错误提到了本地数据库运行时和 SQL Server Express,而我在代码中的任何地方都没有引用。系统指向 Azure SQL 数据库。工作是 ADO.Net,我对连接字符串进行了硬编码,以尝试消除基于配置的连接字符串的任何问题。但奇怪的是,它只发生在消息的特定部分。其他处理完美。

最后,我 运行 在本地调试作业(仍然指向 Azure 上的真实队列和数据库)并遇到了同样的问题。但是作业会输出一个控制台行,其中作业 ID 作为代码的第一行。对于那些成功处理的作业,我看到了这个 writeline。对于那些失败的人,我什么也看不到。这几乎就像工作没有真正正确启动一样。 (失败的作业也有很短的 运行 时间 50-100 毫秒)

我在一些工作中遇到了同样的问题,我浏览了这些文章以找到解决方案:

来自论文文章:

瞬时故障的原因

在云环境中,您会发现数据库连接失败和丢失会定期发生。这在一定程度上是因为与 Web 服务器和数据库服务器具有直接物理连接的本地环境相比,您要使用更多的负载均衡器。此外,有时当您依赖多租户服务时,您会看到对该服务的调用变慢或超时,因为使用该服务的其他人正在严重打击它。在其他情况下,您可能是过于频繁地访问该服务的用户,并且该服务故意限制您 - 拒绝连接 - 以防止您对服务的其他租户产生不利影响。

使用智能 retry/back-off 逻辑来减轻瞬态故障的影响:

如果您使用 ADO.NET 数据库,Microsoft 模式与实践小组有一个 Transient Fault Handling Application Block 可以为您完成所有工作访问(不是通过 Entity Framework)。您只需设置重试策略——重试查询或命令的次数以及两次尝试之间等待的时间——然后将 SQL 代码包装在一个 using 块中:

public void HandleTransients()
{
   var connStr = "some database";
   var _policy = RetryPolicy.Create < SqlAzureTransientErrorDetectionStrategy(
    retryCount: 3,
    retryInterval: TimeSpan.FromSeconds(5));

    using (var conn = new ReliableSqlConnection(connStr, _policy))
    {
        // Do SQL stuff here.
    }
}

当您使用 Entity Framework 时,您通常不会直接使用 SQL 连接,因此您不能使用此模式和实践包, 但 Entity Framework 6 将这种重试逻辑直接构建到框架中。以类似的方式指定重试策略,然后 EF 在访问数据库时使用该策略。

To use this feature in the Fix It app, all we have to do is add a class that derives from DbConfiguration and turn on the retry logic.

// EF follows a Code based Configuration model and will look for a class that
// derives from DbConfiguration for executing any Connection Resiliency strategies
public class EFConfiguration : DbConfiguration
{
    public EFConfiguration()
    {
        AddExecutionStrategy(() => new SqlAzureExecutionStrategy());
    }
}