本文介绍如何在 Azure Functions 中使用计时器触发器。 计时器触发器可以按计划运行函数。

此参考信息面向 Azure Functions 开发人员。 Azure Functions 的新手请从以下资源入手:

  • Azure Functions 开发人员参考。
  • 创建第一个函数

  • C# 开发人员参考:

  • 进程内类库
  • 独立工作进程类库
  • C# 脚本
  • 若要了解如何手动运行计时器触发的函数,请参阅 手动运行非 HTTP 触发的函数

    在所有开发环境中自动提供对该绑定的支持。 无需手动安装包或注册扩展。

    azure-webjobs-sdk-extensions GitHub 存储库中提供了计时器扩展包的源代码。

    Azure Functions 支持两种 Python 编程模型。 定义绑定的方式取决于选择的编程模型。

    此示例演示一个 C# 函数,每次分钟数为 5 的倍数值时执行该函数。 例如,当函数从 18:55:00 开始时,下一次执行为 19:00:00。 TimerInfo 对象将传递到函数中。

    可以使用以下 C# 模式之一创建 C# 函数:

  • 进程内类库 :编译的 C# 函数,该函数在与 Functions 运行时相同的进程中运行。
  • 独立工作进程类库 :编译的 C# 函数,该函数在独立于运行时的工作进程中运行。 需要独立的工作进程才能支持在非 LTS 版 .NET 和 .NET Framework 上运行的 C# 函数。
  • C# 脚本 :主要在 Azure 门户中创建 C# 函数时使用。
  • [FunctionName("TimerTriggerCSharp")]
    public static void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger log)
        if (myTimer.IsPastDue)
            log.LogInformation("Timer is running late!");
        log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
    [Function("TimerFunction")]
    [FixedDelayRetry(5, "00:00:10")]
    public static void Run([TimerTrigger("0 */5 * * * *")] TimerInfo timerInfo,
        FunctionContext context)
        var logger = context.GetLogger("TimerFunction");
        logger.LogInformation($"Function Ran. Next timer schedule = {timerInfo.ScheduleStatus.Next}");
    

    以下示例演示 function.json 文件中的一个计时器触发器绑定以及使用该绑定的 C# 脚本函数。 该函数将写入日志信息,指示调用此函数是由于错过了计划发生时间。 TimerInfo 对象将传递到函数中。

    下面是 function.json 文件中的绑定数据:

    "schedule": "0 */5 * * * *", "name": "myTimer", "type": "timerTrigger", "direction": "in"

    C# 脚本代码如下所示:

    public static void Run(TimerInfo myTimer, ILogger log)
        if (myTimer.IsPastDue)
            log.LogInformation("Timer is running late!");
        log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}" );  
    

    以下示例函数的触发和执行间隔为 5 分钟。 函数上的 @TimerTrigger 注释使用与 CRON 表达式相同的字符串格式定义计划。

    @FunctionName("keepAlive")
    public void keepAlive(
      @TimerTrigger(name = "keepAliveTrigger", schedule = "0 */5 * * * *") String timerInfo,
          ExecutionContext context
         // timeInfo is a JSON string, you can deserialize it to an object using your favorite JSON library
         context.getLogger().info("Timer is triggered: " + timerInfo);
    

    以下示例显示了计时器触发器绑定和使用绑定的函数代码(其中表示计时器的实例传递给函数)。 该函数将写入日志信息,指示调用此函数是由于错过了计划发生时间。 该示例取决于使用的是 v1 还是 v2 Python 编程模型

    @app.function_name(name="mytimer") @app.schedule(schedule="0 */5 * * * *", arg_name="mytimer", run_on_startup=True) def test_function(mytimer: func.TimerRequest) -> None: utc_timestamp = datetime.datetime.utcnow().replace( tzinfo=datetime.timezone.utc).isoformat() if mytimer.past_due: logging.info('The timer is past due!') logging.info('Python timer trigger function ran at %s', utc_timestamp)

    JavaScript 代码如下所示:

    module.exports = async function (context, myTimer) {
        var timeStamp = new Date().toISOString();
        if (myTimer.isPastDue)
            context.log('Node is running late!');
        context.log('Node timer trigger function ran!', timeStamp);   
    # Get the current universal time in the default string format.
    $currentUTCtime = (Get-Date).ToUniversalTime()
    # The 'IsPastDue' property is 'true' when the current function invocation is later than scheduled.
    if ($myTimer.IsPastDue) {
        Write-Host "PowerShell timer is running late!"
    # Write an information log with the current time.
    Write-Host "PowerShell timer trigger function ran! TIME: $currentUTCtime"
    

    下面是 Python 代码,其中传入函数的对象的类型为 azure.functions.TimerRequest 对象

    import datetime
    import logging
    import azure.functions as func
    def main(mytimer: func.TimerRequest) -> None:
        utc_timestamp = datetime.datetime.now(datetime.timezone.utc).isoformat()
        if mytimer.past_due:
            logging.info('The timer is past due!')
        logging.info('Python timer trigger function ran at %s', utc_timestamp)
    

    进程内 C# 库使用 Microsoft.Azure.WebJobs.Extensions 中的 TimerTriggerAttribute 来定义函数,而独立工作进程 C# 库使用 Microsoft.Azure.Functions.Worker.Extensions.Timer 中的 TimerTriggerAttribute 来定义函数。

    C# 脚本改为使用 function.json 配置文件。

    C# 脚本 CRON 表达式TimeSpan 值。 只能对在应用服务计划中运行的函数应用使用 TimeSpan。 可以将计划表达式放在应用设置中并将此属性设置为用 % 符号括起的应用设置名称,例如 %ScheduleAppSetting%RunOnStartup 如果为 true,则在运行时启动时调用此函数。 例如,当函数应用从由于无活动而进入的空闲状态醒来后,运行时会启动。 当函数应用由于函数更改而重新启动时,以及当函数应用横向扩展时。请谨慎使用。RunOnStartup 应很少设置为 true(如果曾经设置过),尤其是在生产中。 UseMonitor 设置为 truefalse 以指示是否应当监视计划。 计划监视在各次计划发生后会持续存在,以帮助确保即使在函数应用实例重新启动的情况下也能正确维护计划。 如果未显式设置,则对于重复周期间隔大于或等于 1 分钟的计划,默认值为 true。 对于每分钟触发多次的计划,默认值为 falseCRON 表达式TimeSpan 值。 只能对在应用服务计划中运行的函数应用使用 TimeSpan。 可以将计划表达式放在应用设置中并将此属性设置为用 % 符号括起的应用设置名称,例如 %ScheduleAppSetting%RunOnStartup 如果为 true,则在运行时启动时调用此函数。 例如,当函数应用从由于无活动而进入的空闲状态醒来后,运行时会启动。 当函数应用由于函数更改而重新启动时,以及当函数应用横向扩展时。请谨慎使用。RunOnStartup 应很少设置为 true(如果曾经设置过),尤其是在生产中。 UseMonitor 设置为 truefalse 以指示是否应当监视计划。 计划监视在各次计划发生后会持续存在,以帮助确保即使在函数应用实例重新启动的情况下也能正确维护计划。 如果未显式设置,则对于重复周期间隔大于或等于 1 分钟的计划,默认值为 true。 对于每分钟触发多次的计划,默认值为 falseschedule CRON 表达式TimeSpan 值。 只能对在应用服务计划中运行的函数应用使用 TimeSpan。 可以将计划表达式放在应用设置中并将此属性设置为用 % 符号括起的应用设置名称,例如此示例中的“%ScheduleAppSetting%”。 runOnStartup 如果为 true,则在运行时启动时调用此函数。 例如,当函数应用从由于无活动而进入的空闲状态醒来后,运行时会启动。 当函数应用由于函数更改而重新启动时,以及当函数应用横向扩展时。谨慎使用。runOnStartup 应很少设置为 true(如果曾经设置过),尤其是在生产中。 useMonitor 设置为 truefalse 以指示是否应当监视计划。 计划监视在各次计划发生后会持续存在,以帮助确保即使在函数应用实例重新启动的情况下也能正确维护计划。 如果未显式设置,则对于重复周期间隔大于或等于 1 分钟的计划,默认值为 true。 对于每分钟触发多次的计划,默认值为 falseschedule CRON 表达式TimeSpan 值。 只能对在应用服务计划中运行的函数应用使用 TimeSpan。 可以将计划表达式放在应用设置中并将此属性设置为用 % 符号括起的应用设置名称,例如此示例中的“%ScheduleAppSetting%”。 run_on_startup 如果为 true,则在运行时启动时调用此函数。 例如,当函数应用从由于无活动而进入的空闲状态醒来后,运行时会启动。 当函数应用由于函数更改而重新启动时,以及当函数应用横向扩展时。谨慎使用。runOnStartup 应很少设置为 true(如果曾经设置过),尤其是在生产中。 use_monitor 设置为 truefalse 以指示是否应当监视计划。 计划监视在各次计划发生后会持续存在,以帮助确保即使在函数应用实例重新启动的情况下也能正确维护计划。 如果未显式设置,则对于重复周期间隔大于或等于 1 分钟的计划,默认值为 true。 对于每分钟触发多次的计划,默认值为 false

    对于使用 function.json 定义的 Python 函数,请参阅配置部分。

    函数上的 @TimerTrigger 注释使用与 CRON 表达式相同的字符串格式定义 schedule。 该注释支持以下设置:

  • dataType
  • schedule
  • 仅适用于 Python v1 编程模型。

    下表解释了在 function.json 文件中设置的绑定配置属性。

    function.json 属性 schedule CRON 表达式TimeSpan 值。 只能对在应用服务计划中运行的函数应用使用 TimeSpan。 可以将计划表达式放在应用设置中并将此属性设置为用 % 符号括起的应用设置名称,例如此示例中的“%ScheduleAppSetting%”。 runOnStartup 如果为 true,则在运行时启动时调用此函数。 例如,当函数应用从由于无活动而进入的空闲状态醒来后,运行时会启动。 当函数应用由于函数更改而重新启动时,以及当函数应用横向扩展时。谨慎使用。runOnStartup 应很少设置为 true(如果曾经设置过),尤其是在生产中。 useMonitor 设置为 truefalse 以指示是否应当监视计划。 计划监视在各次计划发生后会持续存在,以帮助确保即使在函数应用实例重新启动的情况下也能正确维护计划。 如果未显式设置,则对于重复周期间隔大于或等于 1 分钟的计划,默认值为 true。 对于每分钟触发多次的计划,默认值为 false

    请勿在生产环境中将 runOnStartup 设置为 true。 使用此设置会使代码在非常不可预测的时间执行。 在某些生产设置中,这些额外执行可能会导致消耗计划中托管的应用产生明显更高的成本。 例如,启用 runOnStartup 后,只要缩放函数应用,就会调用触发器。 在生产中启用 runOnStartup 之前,请确保完全了解函数的生产行为。

    有关完整示例,请参阅示例部分

    调用计时器触发器函数时,计时器对象将传递到函数中。 以下 JSON 是计时器对象的示例表示形式。

    "Schedule":{ "AdjustForDST": true "ScheduleStatus": { "Last":"2016-10-04T10:15:00+00:00", "LastUpdated":"2016-10-04T10:16:00+00:00", "Next":"2016-10-04T10:20:00+00:00" "IsPastDue":false

    如果当前函数调用晚于计划时间,则 isPastDue 属性为 true。 例如,函数应用重新启动可能会导致调用被错过。

    NCRONTAB 表达式

    Azure Functions 使用 NCronTab 库来解释 NCRONTAB 表达式。 NCRONTAB 表达式类似于 CRON 表达式,不同之处在于它在开头包含额外的第六个字段,用于以秒为单位的时间精度:

    {second} {minute} {hour} {day} {month} {day-of-week}

    每个字段可以具有下列类型之一的值:

    NCRONTAB 时区

    CRON 表达式中的数字指的是时间和日期,而不是时间跨度。 例如,hour 字段中的 5 指的是 5:00 AM,而不是每 5 小时。

    CRON 表达式使用的默认时区为协调世界时 (UTC)。 若要让 CRON 表达式基于其他时区,请为你的函数应用创建一个名为 WEBSITE_TIME_ZONE 的应用设置。

    此设置的值取决于运行函数应用的操作系统和计划。

    Linux 消耗计划目前不支持 WEBSITE_TIME_ZONE

    例如,美国东部时间(由 Eastern Standard Time (Windows) 或 America/New_York (Linux) 表示)当前在标准时间中使用 UTC-05:00,在夏令时中使用 UTC-04:00。 若要使计时器触发器每天在东部时间上午 10:00 触发,请为函数应用创建一个名为 WEBSITE_TIME_ZONE 的应用设置并将值设置为 Eastern Standard Time (Windows) 或 America/New_York (Linux),然后使用以下 NCRONTAB 表达式:

    "0 0 10 * * *"
    

    使用 WEBSITE_TIME_ZONE 时,时间将针对特定时区中的时间更改进行调整,包括夏令时和标准时间的更改。

    TimeSpan

    只能对在应用服务计划中运行的函数应用使用 TimeSpan

    与 CRON 表达式不同,TimeSpan 值指定各次函数调用之间的时间间隔。 如果函数的运行时间超出了指定的时间间隔,则在函数完成时,计时器会立即再次调用该函数。

    以字符串表示,当 hh 小于 24 时,TimeSpan 格式为 hh:mm:ss。 当前两个数字是 24 或更大的数字时,格式为 dd:hh:mm。 下面是一些示例:

    可以省略标识值,也可以手动将每个函数应用的标识配置设置为不同的值。

    计时器触发器使用存储锁来确保当函数应用横向扩展到多个实例时将只有一个计时器实例。 如果两个函数应用共享相同的标识配置,并且每个函数应用都使用一个计时器触发器,则只有一个计时器运行。

    与队列触发器不同,计时器触发器在函数失败后不会重试。 函数失败时,在计划的下次时间到来前,不会再次调用该函数。

    手动调用计时器触发器

    Azure Functions 的计时器触发器提供了 HTTP Webhook,可以通过调用它来手动触发函数。 这在以下方案中非常有用。

  • 槽交换是冒烟测试或预热活动的一部分
  • 函数的初始部署,以立即在数据库中填充缓存或查找表
  • 若要详细了解如何手动调用计时器触发的函数,请参阅手动运行非 HTTP 触发的函数

    有关在计时器触发器未按预期工作的情况下应采取的措施,请参阅调查和报告有关计时器触发功能未触发的问题

    转到有关使用计时器触发器的快速入门

    详细了解 Azure Functions 触发器和绑定