HangFire进阶

发布时间 2023-06-14 01:03:14作者: 广州大雄

免费版有什么限制

Hangfire 提供了两个版本:Community 版本和商业版(Enterprise Edition)。其中,Community 版本是免费的,而商业版需要购买许可证。

免费版

  • 仅支持使用 SQL Server、PostgreSQL、MySQL 和 Redis 作为存储后端,无法使用 Oracle、MongoDB 等其他数据库。
  • 不能使用商业版中的一些高级功能,如实时控制面板、批量作业以及持续性集合等。
  • 开源协议要求必须公开源代码,无法闭源定制或二次开发。
  • 只能在开源协议下进行使用和分发,不能用于商业行为或盈利。

hangfire 是如何传递方法与参数的

在 Hangfire 中,要将一个方法包装成一个后台作业,并添加到 Hangfire 的队列中执行,有多种方式可以实现。下面是其中的两种方式:
使用 Lambda 表达式最简单的方式是直接将待执行的方法体写在 Lambda 表达式中,并将该表达式作为参数传递给 Hangfire
BackgroundJob.Enqueue(() => DoSomething());
其中,DoSomething() 是待执行的方法。Hangfire 会将该 Lambda 表达式封装成一个后台作业,并将其添加到 Hangfire 的队列中等待执行。

另一种方式是使用反射来调用待执行的方法。这种方式需要指定方法名、类名和参数,如下所示:
BackgroundJob.Enqueue(() => MyClass.MyMethod("param1", 123));
其中,MyClass 是包含待执行方法的类名,MyMethod 是待执行方法的名称,"param1" 和 123 则是方法的参数。Hangfire 会使用反射来调用指定的方法,并将其封装成一个后台作业添加到 Hangfire 队列中等待执行。

无论使用哪种方式,Hangfire 都会将要执行的方法和参数序列化成 JSON 格式,并存储到 Hangfire 的存储中(如 SQL Server、Redis 等),以便在之后的某个时间点重新加载该数据,并根据其中的信息来执行作业。当作业开始执行时,Hangfire 会将该 JSON 数据反序列化成对应的方法和参数,并在独立的线程中执行该方法。

任务数据存放在job

image
image

执行结果数据state

image

hangfire如何实现多负载

在不同的服务器上部署多个 Hangfire 服务,并将这些服务连接到同一个存储后端(如 SQL Server、Redis 等)。这样每个服务都会独自运行,并从存储后端中获取待执行的作业信息并执行作业。由于所有服务连接到同一个存储后端,因此它们可以共享作业的执行状态以及作业执行日志等信息。

BackgroundJobServerOptions比较重要的参数

image

SchedulePollingInterval

SchedulePollingInterval 时间间隔越短,扫描计划作业队列的频率越高,可以更快地发现过期任务并执行,但也会增加后台处理器的负担和资源占用。
SchedulePollingInterval 时间间隔越长,则意味着扫描计划作业队列的频率越低,系统负担和资源占用也相应减少,但可能会导致过期任务无法及时执行。
需要注意的是,SchedulePollingInterval 参数仅控制计划作业队列的扫描间隔,即对那些尚未到期的计划任务不会产生影响。而一旦检测到计划任务已到期,则 Hangfire 会立即将其添加到普通作业队列中,等待后台处理器执行。因此,SchedulePollingInterval 参数的合理设置,可以帮助您控制和优化 Hangfire 后台任务处理的性能表现和资源消耗。

WorkerCount

WorkerCount 是 Hangfire 中 BackgroundJobServerOptions 类型的一个参数,表示该服务器允许同时处理的工作者数量。简单来说,WorkerCount 参数指定了可以同时并行处理多少个作业任务,也就是可以同时运行多少个 Job。

Queues

Queues 是 Hangfire 中 BackgroundJobServerOptions 类型的一个参数,用于指定可以处理的作业队列名称。简单来说,Queues 参数允许您将作业任务分配到不同的队列中,以便使用不同的处理器来处理这些队列,从而实现作业任务的优先级和分组管理。

//在 Enqueue 方法中,可以通过传递第二个参数 queueName 来指定要将作业添加到哪个队列中。例如,以下代码将发送电子邮件任务添加到名为 "email" 的队列
BackgroundJob.Enqueue(() => SendEmail("hello@example.com"), "email");

GlobalJobFilters

//作业日志
GlobalJobFilters.Filters.Add(new LogJobFilterAttribute());
//自动重试功能
GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 0 });

hangFire server 如何优雅的关闭服务器

var server = new BackgroundJobServer();
// 做一些其它事情...
server.SendStop();

在上述示例中,首先创建了一个新的 BackgroundJobServer 实例,然后在该实例上执行了一些其它操作。最后,调用 SendStop() 方法来关闭服务器,它将等待所有正在运行的作业完成后才会关闭。