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

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

   SlidingInvisibilityTimeout = TimeSpan.FromMinutes(30),
   QueuePollInterval = TimeSpan.FromHours(5)

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

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

寻求这方面的帮助。

编辑:每秒执行以下查询:
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'

与我们设置的时间跨度值的各种组合无关。这是我们使用的 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;
    }

worker 数量仅设置为 5。

只有 4 个作业,甚至这些作业都已完成(SELECT * FROM [HangFire].[State]):
c# - Hangfire 导致 SQL Server 中的锁定-LMLPHP

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

最佳答案

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

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

关于c# - Hangfire 导致 SQL Server 中的锁定,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56321781/

10-12 23:44