如何估算 Hangfire 中的作业完成时间

How to approximate job completion times in Hangfire

我有一个应用程序使用 hangfire 为我做长时间的 运行 工作(我知道工作需要的时间并且它总是大致相同),并且在我的 UI 我想估计某项工作何时完成。为此,我需要查询 hangfire 以了解作业在队列中的位置以及处理它的服务器数量。

我知道我可以通过

获得排队作业的数量(在"DEFAULT"队列中)
public long JobsInQueue() {
    var monitor = JobStorage.Current.GetMonitoringApi();
    return monitor.EnqueuedCount("DEFAULT");
}

服务器数量

public int HealthyServers() {
    var monitor = JobStorage.Current.GetMonitoringApi();
    return monitor.Servers().Count(n => (n.Heartbeat != null) && (DateTime.Now - n.Heartbeat.Value).TotalMinutes < 5);
}

(顺便说一句:我排除了较旧的心跳,因为如果我关闭服务器,它们有时会在 hangfire 数据库中徘徊。有更好的方法吗?),但要给出正确的估计,我需要知道工作的位置在队列中。我如何获得它?

你遇到的问题是 hangfire 是异步的、排队的、并行的,表现出至少一次的持久性语义,并且基本上是不确定的。

确定地知道一个项目在这样的系统中完成处理的顺序是不可能的。事实上,如果要求强制执行严格的排序,那么 hangfire 的许多好处就会消失。

@odinserj(hangfire 的作者)有一篇非常好的博客 post,他概述了这一点:http://odinserj.net/2014/05/10/are-your-methods-ready-to-run-in-background/

然而,也就是说,提出一个合理的估计算法并非不可能,但它必须是以某种方式近似执行顺序的算法。至于如何得出这样的算法,我不知道,但像这样的 可能 有效(但可能不会):

Approximate seconds remaining until completion = 
    (
        (average duration of job in seconds * queue depth)
        / (the lower of: number of hangfire threads OR queue depth)
    ) 
    - number of seconds already spent in queue 
    + average duration of job in seconds