Hangfire在SQL Server中导致锁定

Rag*_*hav 9 c# sql-server backgroundworker hangfire

我们在带有SQL Server 2016的ASP.NET Web项目中使用Hangfire 1.7.2。我们的服务器上大约有150个站点,每个站点都使用Hangfire 1.7.2。我们注意到,当我们升级这些站点以使用Hangfire时,数据库服务器崩溃了。查看数据库日志,我们发现有多个锁定查询。我们在所有阻止会话中都标识了一个RPC事件“ sys.sp_getapplock; 1”。看来Hangfire锁定了我们的数据库,使整个数据库无法使用。由于Hangfire,我们注意到将近670多个锁定查询。

这可能是由于我们设置了以下属性:

   SlidingInvisibilityTimeout = TimeSpan.FromMinutes(30),
   QueuePollInterval = TimeSpan.FromHours(5)
Run Code Online (Sandbox Code Playgroud)

每个站点大约有20个后台作业,其中一些每分钟运行一次,而另一些每小时,每6小时运行一次,每天运行一次。

我已经搜索了文档,但是找不到任何可以解释这两个属性或如何设置它们以避免数据库锁定的内容。

在这方面寻求帮助。

编辑:每秒执行以下查询:

exec sp_executesql N'select count(*) from [HangFire].[Set] with (readcommittedlock, forceseek) where [Key] = @key',N'@key nvarchar(4000)',@key=N'retries'

select distinct(Queue) from [HangFire].JobQueue with (nolock)

exec sp_executesql N'select count(*) from [HangFire].[Set] with (readcommittedlock, forceseek) where [Key] = @key',N'@key nvarchar(4000)',@key=N'retries'
Run Code Online (Sandbox Code Playgroud)

不管我们设置的时间跨度值的各种组合如何。这是我们正在使用的GetHangfirServers的代码:

  public static IEnumerable<IDisposable> GetHangfireServers()
    {
        // Reference for GlobalConfiguration.Configuration: http://docs.hangfire.io/en/latest/getting-started/index.html
        // Reference for UseSqlServerStorage: http://docs.hangfire.io/en/latest/configuration/using-sql-server.html#configuring-the-polling-interval
        GlobalConfiguration.Configuration
            .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)

            .UseSimpleAssemblyNameTypeSerializer()
            .UseRecommendedSerializerSettings()
            .UseSqlServerStorage(ConfigurationManager.ConnectionStrings["abc"]
                .ConnectionString, new SqlServerStorageOptions
            {
                CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
                SlidingInvisibilityTimeout = TimeSpan.FromMinutes(30),
                QueuePollInterval = TimeSpan.FromHours(5), // Hangfire will poll after 5 hrs to check failed jobs.
                UseRecommendedIsolationLevel = true,
                UsePageLocksOnDequeue = true,
                DisableGlobalLocks = true
            });

        // Reference: https://docs.hangfire.io/en/latest/background-processing/configuring-degree-of-parallelism.html
        var options = new BackgroundJobServerOptions
        {
            WorkerCount = 5
        };

        var server = new BackgroundJobServer(options);

        yield return server;
    }
Run Code Online (Sandbox Code Playgroud)

工人数仅设置为5。

只有4个工作,甚至完成了(SELECT * FROM [HangFire]。[State]): 在此处输入图片说明

您是否知道为什么Hangfire每秒会遇到如此多的查询?

小智 7

我们在我们的一个项目中遇到了这个问题。hangfire仪表板读起来很繁琐,它非常频繁地轮询hangfire数据库,以刷新作业状态。

最适合我们的解决方案是拥有专用的hangfire数据库。这样,您可以将应用程序查询与hangfire查询隔离开,并且您的应用程序查询将不受hangfire服务器和仪表板查询的影响。

  • 另一个好主意是将“ DashboardOptions.StatsPollingInterval”更改为“ 600000”(10分钟)之类的值。这减慢了hangfire仪表板自动刷新的频率(您始终可以手动刷新)。 (3认同)