Hangfire вызывает блокировки в SQL Server - PullRequest
5 голосов
/ 27 мая 2019

Мы используем Hangfire 1.7.2 в нашем веб-проекте ASP.NET с SQL Server 2016. На нашем сервере около 150 сайтов, каждый из которых использует Hangfire 1.7.2.Мы заметили, что когда мы обновили эти сайты для использования Hangfire, сервер БД рухнул.Проверяя журналы БД, мы обнаружили, что было несколько запросов на блокировку.Мы идентифицировали одно событие RPC «sys.sp_getapplock; 1» во всех сеансах блокировки.Кажется, что Hangfire блокирует нашу БД, делая всю БД непригодной для использования.Мы заметили почти 670+ запросов на блокировку из-за Hangfire.

Это может быть связано с настройкой этих свойств:

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

На каждом сайте есть около 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'

независимо от различных комбинаций значений временного интервала, которые мы установили.Вот код 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;
    }

Количество рабочих задано равным 5.

Есть только 4 задания, и даже они выполнены (ВЫБРАТЬ * ОТ [HangFire]. [State]): enter image description here

У вас есть идея, почему Hangfire выполняет так много запросов в секунду?

1 Ответ

3 голосов
/ 03 июня 2019

Мы столкнулись с этой проблемой в одном из наших проектов. Панель управления hangfire довольно тяжело читается и очень часто опрашивает базу данных hangfire, чтобы обновить статус задания.

Лучшее решение, которое сработало для нас, - это выделенная база данных Hangfire. Таким образом вы изолируете запросы приложений от запросов зависания, и запросы приложений не будут зависеть от запросов сервера зависания и панели мониторинга.

...