当托管在 Azure 上时,警报被安排晚一个小时

Alert getting scheduled an hour late when hosted on Azure

我正在使用 hangfire 安排在用户指定的时间发送电子邮件警报。当我在本地主机上测试应用程序时,警报被安排在正确的时间,当我向 Azure 上托管的实时应用程序发送请求时,请求被安排在一个小时后。

我认为问题是我对 DateTimeOffset 缺乏了解。我在 JobScheduler class 中所做的是

    public class JobScheduler : IJobScheduler
    {
        private EmailManager _emailManager;

        public JobScheduler(IAlertManager alertManager)
        {
            _alertManager = alertManager;
        }
        public string ScheduleRaiseDateAlert( DateDetail date)
        {
            DateTimeOffset jobRunTime = ConvertToDateTimeOffSet(date.CheckInTime);
            return BackgroundJob.Schedule(()=> _alertManager.RaiseAlertAsync(date.Id, true), jobRunTime.DateTime);
        }
        private DateTimeOffset ConvertToDateTimeOffSet(DateTime futureDateTime)
        {
            futureDateTime = DateTime.SpecifyKind(futureDateTime, DateTimeKind.Utc);
            DateTimeOffset ScheduleTime = futureDateTime;
            return ScheduleTime;
        }
    }

date.CheckInTime 是应该向用户发送电子邮件的日期时间

例如:如果 date.CheckInTime = 17/04/2018 19:02:00 当我发送请求时在本地主机上,作业将安排在该日期和时间,当我向 azure 上托管的应用程序发送相同的请求时,作业安排的时间是 17/04/2018 20:02:00

AFAIK,DateTimeOffset.DateTime 将被视为本地日期时间,您可以检查发送到 BackgroundJob.SchedulejobRunTime.DateTime 实例的 Kind 属性 ].

对于支持 DateTimeOffset 参数的 BackgroundJob.Schedule 的方法重载,存储的 EnqueueAt 将是您的 DateTimeOffsetDateTimeOffset.UtcDateTime =] 参数.

对于 TimeSpan 参数,存储的 EnqueueAt 将是当前 UTC 日期时间加上您指定的 TimeSpan。

此外,如果您将本地时间 DateTime 实例传递给 BackgroundJob.Schedule,存储的 EnqueueAt 将被转换为相关的 UTC 日期时间。

由于您没有提供如何构建 DateDetail,我建议您检查存储的任务以缩小此问题的范围。我使用了 UseSqlServerStorage,对于这种方法,您可以在 HangFire.State table.

下查看计划任务的状态
{"EnqueueAt":"2018-04-20T06:39:28.0305044Z","ScheduledAt":"2018-04-18T06:39:29.5398973Z"}

ScheduledAt代表你创建这个任务的UTC日期时间,EnqueueAt代表任务触发的UTC日期时间。