我们目前在纯python中有一个不知道时区的调度程序。
它使用有序事件的heapq(python二进制堆),包含回调的时间,回调和参数。它从heapq获取最少值的时间,计算事件发生前的秒数,并在运行作业之前休眠该秒数。
我们不必担心计算机被暂停;这是在专用服务器上运行,而不是笔记本电脑。
我们希望让调度程序能够很好地应对时区变化,所以我们在11月份没有问题,就像我们最近做的那样(我们有一项重要的工作需要在数据库中进行调整才能使其运行上午8:15而不是上午9:15 - 通常在上午8:15运行。我想我们可以:
这听起来是对的吗?它可能在哪里?
谢谢!
答案 0 :(得分:1)
我之前曾就其他编程语言编写了几次调度问题。这些概念对python也有效。您可能希望阅读其中一些帖子:1,2,3,4,5,6
我将尝试从Python的角度再次解决具体问题:
将重复发生模式与执行时间分开是很重要的。重复发生模式应该存储用户输入时间的时间,通常是本地时间。即使重复发生模式只是一次",它仍然应该存储为本地时间。调度是少数几个使用案例中的一个,其中"的常见建议始终在UTC" 中不起作用!
您还需要存储时区标识符。这些应为IANA时区,例如America/Los_Angeles
或Europe/London
。在Python中,您可以使用pytz库来处理这些时区。
执行时间应该基于UTC。任何事件的 next 执行时间应根据重复模式中的本地时间计算。您可能希望提前计算并存储这些执行时间,以便您可以轻松确定要运行的下一个事件。
您应该准备重新计算这些执行时间。您可能希望定期执行此操作,但至少应在将时区更新应用于系统时执行此操作。您可以(并且应该)订阅tz update announcements from IANA,然后查找相应的pytz updates on pypi。
这样想。当您将本地时间转换为UTC时,您假设您知道该时间点将的时区规则,但 nobody 可以预测什么政府将来会这样做。时区规则可以改变,而且他们经常这样做。你需要考虑到这一点。
您应该测试无效和模糊的时间,并制定处理它们的计划。这些在安排时很容易被击中,特别是对于重复发生的事件。
例如,您可以安排任务在每天凌晨2:00运行 - 但是在春季转发当天,该时间不存在。那你该怎么办?在许多情况下,您希望在当天凌晨3:00运行,因为它是在1:59 AM之后的下一次。但在某些(更罕见的)情境中,您可能会在凌晨1点或凌晨1点59分运行,或者完全跳过那一天。
同样,您可以安排任务在每天凌晨1:00运行,但在回退过渡当天,凌晨1:00发生两次。所以你会怎么做?在许多情况下,第一个实例(即 daylight 实例)是正确的触发时间。在其他(更罕见的)情况下,第二个实例可能更合适,或者(甚至更罕见)实际运行两次作业可能是合适的。
关于以every X [hours/minutes/seconds]
类型计划运行的作业:
这些最容易按UTC安排,不应受DST更改的影响。
如果这些是您正在运行的仅类型的作业,您可以将整个系统基于UTC。但是,如果您正在运行不同类型的工作,那么您可以考虑只设置"本地时区"成为" UTC"在重现模式中。
或者,您可以按真正的本地时间安排它们,只需确保在作业运行时根据当前执行时间计算下一个执行时间,该时间应该已经是UTC。
您不应该区分超过每小时运行的作业或运行时间少于每小时的作业。我希望在回退过渡当天每小时运行25次,在春季前进过渡当天运行23次。
关于你的睡眠计划和每分钟唤醒一次 - 这可能会工作,只要你没有处理亚分钟任务。但它可能不一定是处理它的最有效方式。如果正确预先计算并存储执行时间,则可以将单个任务设置为在下次运行时唤醒,运行需要运行的所有内容,然后为下一个执行时间设置新任务。你不必每分钟醒来一次。
您还应该考虑运行预定作业所需的资源。如果您安排所有需要在午夜运行的1000个任务,会发生什么?好吧,他们不一定能够在一台计算机上同时运行。您可以将它们排队以便批量运行,或将负载分散到不同的时间段。在云环境中,您可能会启动其他工作人员来处理负载。