Celery时区的预定任务问题 [英] Celery scheduled tasks problems with Timezone

查看:192
本文介绍了Celery时区的预定任务问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在服务器时间现在为 BST 的服务器中使用celery,突然我的计划任务在一个小时前执行!以前,服务器时间为欧洲/伦敦是格林尼治标准时间(GMT),但现在由于夏令时而成为BST(GMT + 1)

I'm using celery in a server where server time is now BST, and suddenly my scheduled tasks are executing one hour before! Previously, server time was Europe/London which was GMT but now due to day light saving it has become BST (GMT + 1)

我已将celery配置为使用时区,例如:

I've configured celery to use the timezone like:

CELERY_TIMEZONE = 'Europe/London'

然后在调用任务时,我也将 eta 参数的值本地化为欧洲/伦敦,如下所示:

Then when calling tasks, I've also localized value for the eta parameter to 'Europe/London' like this:

from datetime import datetime
from pytz import timezone

locale_to_use = timezone('Europe/London')
current_time = locale_to_use.localize(datetime.now())

并使用了 current_time 作为调用任务时 eta 参数的值。

And used this current_time as value of eta parameter when calling task.

现在我在本地化 eta 参数值?我的服务器在BST中。

Now is there any mistake I'm making like localizing the eta parameter value? My server is in BST.

在夏令时生效之前,此配置没有任何问题!

No problems were hapenning with this configuration before the day light saving timezone was in effect!

编辑:

为了清楚起见,我在这里发布代码示例:

To make things clear, I'm posting my code samples here:

@app.task(ignore_result=True)
def eta_test():

    logger.info('Executing eta_test on {0}'.format(datetime.now()))


def run_eta_test(hour, minute):

    now_time = datetime.now()
    target_time = now_time.replace(hour=hour, minute=minute, second=0)

    from settings import options
    from pytz import timezone

    local_zone = timezone('Europe/London')

    target_time = local_zone.localize(target_time)

    eta_test.apply_async(eta=target_time)

然后我从服务器中的python控制台调用run_eta_test,如下所示:

Then I call run_eta_test from a python console in the server, like this:

test_tasks.run_eta_test(17, 17)

也就是说,要在当天的17:17:00执行任务。服务器时间为17:15:45,而不是安排2秒后,它立即执行了任务:

That is, to execute the task on 17:17:00 on the same day. The server time was 17:15:45 and instead of scheduling it 2 seconds after, it executed the task immediately:

[2014-04-04 17:15:45,341: INFO/MainProcess] Received task: scheduling.test_tasks.eta_test[c28448d6-3a51-42f7-9df2-cb93385ff7c6] eta:[2014-04-04 17:17:00.095001+01:00]
[2014-04-04 17:15:46,820: INFO/Worker-3] Executing eta_test on 2014-04-04 17:15:46.820316
[2014-04-04 17:15:46,820: INFO/MainProcess] Task scheduling.test_tasks.eta_test[c28448d6-3a51-42f7-9df2-cb93385ff7c6] succeeded in 0.0008487419690936804s: None

然后我再次调用该任务以在1小时和几秒钟后通过执行如下调用:

Then I called the task again to be executed 1 hour and few seconds later by calling like:

test_tasks.run_eta_test(18, 17)

而不是将其调度到一个小时又几秒钟后,则任务仅在几秒钟后(即一个小时之前)执行:

And instead of scheduling it to one hour and few seconds later, the task executed only few seconds later, that is one hour before:

[2014-04-04 17:16:27,703: INFO/MainProcess] Received task: scheduling.test_tasks.eta_test[f1a54d08-c12d-457f-bee8-04ca35b32242] eta:[2014-04-04 18:17:00.700327+01:00]
[2014-04-04 17:17:01,846: INFO/Worker-2] Executing eta_test on 2014-04-04 17:17:01.846561
[2014-04-04 17:17:01,847: INFO/MainProcess] Task scheduling.test_tasks.eta_test[f1a54d08-c12d-457f-bee8-04ca35b32242] succeeded in 0.0012819559779018164s: None

我的服务器日期配置为BST,例如:

My server date is configured to BST like:

Fri Apr  4 17:29:10 BST 2014

现在,服务器中的时区是否有问题?

Now, is the timezone in the server is being an issue?

再次编辑:

我无法在答案和评论的帮助下解决问题。因此,我所做的就是使用 CELERY_ENABLE_UTC = False ,并且完全没有对 CELERY_ENABLE_UTC 使用任何值。然后,我用我的服务器时间没有任何本地化。 Celery似乎在我的服务器时间正确地安排了任务。

I was not able to solve the problem with the help of the answer and comments. So what I did is, used: CELERY_ENABLE_UTC = False and did not use any value for CELERY_ENABLE_UTC at all. Then, I used my server time without any localization. Celery seemed to schedule tasks correctly at my server time.

推荐答案

您可能会发现将 CELERY_TIMEZONE 设置为'UTC'。然后,如果要使用本地时间安排事件,则可以执行以下操作:

You might find it easier to set your CELERY_TIMEZONE to be 'UTC'. Then, if you want to use Local times to schedule events, you can do the following:

london_tz = pytz.timezone('Europe/London')
london_dt = london_tz.localize(datetime.datetime(year, month, day, hour, min))
give_this_to_celery = london_dt.astimezone(pytz.UTC)

诚然,这是更多的工作。本地化日期时间,然后将其转换并获得原始日期时间。但这应该可以解决大多数时区问题。

Admittedly, this is more work. Localize a datetime, then convert it and get a naive datetime back. But it should take care of most of the headaches from working with timezones.


可以您能否告诉我CELERY_TIMEZONE到底是做什么的?芹菜如何使用eta值计算倒计时?

Can you please tell me what exactly CELERY_TIMEZONE does? And how celery use eta value to calculate countdown?

Celery允许您通过指定 eta来推迟执行函数调用参数。 eta datetime 对象,表示您希望函数何时运行。 CELERY_TIMEZONE 指定用于 eta 的日期时间的时区。因此,如果我们设置 CELERY_TIMEZONE ='America / New_York',我们所有的 eta 参数将被视为

Celery allows you to defer the execution of a function call by specifying the eta parameter. eta is a datetime object that represent when you want the function to be run. CELERY_TIMEZONE specifies the timezone of the datetimes used for eta. So, if we set CELERY_TIMEZONE = 'America/New_York', all of our eta parameters will be interpreted as if they represented New York time.

更好的方法是设置 CELERY_TIMEZONE ='UTC',并传递表示UTC时间戳的datetime对象。这样可以避免很多由于夏令时引起的问题。

Better is to set CELERY_TIMEZONE = 'UTC', and pass datetime objects that represent UTC timestamps. This avoids a lot of the problems caused by daylight savings time.

更多可用信息在文档中

请参阅说明和更正通过asksol讨论注释中eta参数的构造方式。

please see clarification and corrections by asksol on how eta parameter is constructed in the comments.

这篇关于Celery时区的预定任务问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆