当前位置:Gxlcms > 数据库问题 > 使用 EF Core 的 EnableRetryOnFailure 解决短暂的数据库连接失败问题

使用 EF Core 的 EnableRetryOnFailure 解决短暂的数据库连接失败问题

时间:2021-07-01 10:21:17 帮助过:72人阅读

services.AddDbContext<CnblogsDbContext>(options =>
{
    options.UseSqlServer(Configuration.GetConnectionString("cnblogs"),
        builder =>
        {
            builder.EnableRetryOnFailure(
                maxRetryCount: 5,
                maxRetryDelay: TimeSpan.FromSeconds(30),
                errorNumbersToAdd: null);
        });
});
技术图片

但是测试发现不起作用。

期望的测试结果是这样的:启动 asp.net core 站点 ->  curl 发请求 -> 正常响应 -> 停止 SQL Server 服务器 -> curl 发请求 -> 等待 -> 30秒之后启动 SQL Server -> 正常响应。

实际的测试结果却是这样:启动 asp.net core 站点 ->  curl 发请求 -> 正常响应 -> 停止 SQL Server 服务器 -> curl 发请求 -> 15秒左右出现500错误,报上面的异常。

难道这个异常不在 RetryOnFailure 的默认范围?

于是通过 errorNumbersToAdd 添加 0x80131904 错误码:

var errorNumer = 0x80131904;
builder.EnableRetryOnFailure(
    maxRetryCount: 5,
    maxRetryDelay: TimeSpan.FromSeconds(30),
    errorNumbersToAdd: new int[] { (int)errorNumer });

却依然不起作用。

别无他法,只能硬啃 EFCore 的源代码找线索了,于是找到 SqlServerTransientExceptionDetector

技术图片
public class SqlServerTransientExceptionDetector
{
    public static bool ShouldRetryOn([NotNull] Exception ex)
    {
        if (ex is SqlException sqlException)
        {
            foreach (SqlError err in sqlException.Errors)
            {
                switch (err.Number)
                {
                    case 49920:
                    case 49919:
                    case 49918:
                    case 41839:
                    case 41325:
                    case 41305:
                    case 41302:
                    case 41301:
                    case 40613:
                    case 40501:
                    case 40197:
                    case 10929:
                    case 10928:
                    case 64:
                    case 20:
                }
            }

            return false;
        }

        if (ex is TimeoutException)
        {
            return true;
        }

        return false;
    }
}
技术图片

原来是根据 SqlError.Number 来判断的, 上面的数字都这么小,看来 0x80131904 不是 SqlError.Number ,再次查看错误日志发现在 System.Data.SqlClient.SqlException (0x80131904) 之前有下面一行日志:

Error Number:2,State:0,Class:20

原来是 2 ,于是在 errorNumbersToAdd  中添加这个 error number ,问题就解决了。

技术图片
services.AddDbContext<CnblogsDbContext>(options =>
{
    options.UseSqlServer(Configuration.GetConnectionString("cnblogs"),
        builder =>
        {
            builder.EnableRetryOnFailure(
                maxRetryCount: 5,
                maxRetryDelay: TimeSpan.FromSeconds(30),
                errorNumbersToAdd: new int[] { 2 });
        });
});
技术图片

使用 EF Core 的 EnableRetryOnFailure 解决短暂的数据库连接失败问题

标签:not found   state   erro   logs   cond   默认   查看   sys   blog   

人气教程排行