在本地 运行 计时器触发的 Azure 函数一次的最简单方法是什么?

What is the simplest way to run a timer-triggered Azure Function locally once?

我有几个 C# Azure Functions 运行 使用 timer triggers 的时间表。我已经像这样设置它们,其中 %TimerSchedule% 指的是应用程序设置中的 cron 表达式:

public static void Run([TimerTrigger("%TimerSchedule%")]TimerInfo myTimer, TraceWriter log)

在开发过程中,我经常想 运行 使用 Azure Functions Tools for Visual Studio + Azure Functions Core Tools 在本地实现功能。但是,当我按 F5 在本地调试函数时,它(通常)不会立即 运行。相反,它会根据计时器计划开始等待下一次发生。因此,例如,如果我的 cron 表达式说每天晚上 8 点 运行,我必须等到晚上 8 点才能让该函数在我的机器上实际 运行。

所以我的问题是:在本地创建一个函数 运行 的最简单和最好的方法是什么?

我尝试过或考虑过的事情:

  1. 只为本地开发使用更频繁的计时器计划
    • 这还可以,但并不完美——除非它非常频繁,否则您仍然需要稍等片刻,如果非常频繁,那么该函数可能 运行 多次。这就是我现在正在做的。
  2. 编写直接调用函数 Run() 方法的控制台应用程序或单元测试
    • 这不是 100% 简单明了,因为您必须向 Run() 提供 TimerInfoTraceWriter 参数——我发现这方面的文档少得令人吃惊。

Microsoft 的 Strategies for testing your code in Azure Functions 页面在这个主题上不是很有帮助 – 它只提到计时器触发器作为测试 其他 触发器类型的方法。

在一个完美的世界里,我按下 F5,该功能将立即 运行 一次——就像开发一个 "normal" .NET 应用程序一样。

您或许可以使用 RunOnStartup 标志,如记录 here 所示。它不太符合您关于它的简要介绍 运行 一次,但它至少应该在应用程序启动后在本地执行它。

/// Gets or sets a value indicating whether the function should be invoked
/// immediately on startup. After the initial startup run, the function will
/// be run on schedule thereafter.

使用属性绑定的示例:

[TimerTrigger("%TimerSchedule%", RunOnStartup = true)]TimerInfo myTimer

我也有同样的问题。我用 Unittest 修复了它。 事实上,您需要删除 TraceWriter 和 TimerInfo。

这里是我如何做到这一点的一些代码。

定时器信息:

public class ScheduleStub : TimerInfo
{
    public ScheduleStub(TimerSchedule schedule, ScheduleStatus status, bool isPastDue = false) : base(schedule, status, isPastDue)
    {
    }
}

和 TraceWriter:

 public class TraceWriterStub : TraceWriter
{
    protected TraceLevel _level;
    protected List<TraceEvent> _traces;

    public TraceWriterStub(TraceLevel level) : base(level)
    {
        _level = level;
        _traces = new List<TraceEvent>();
    }

    public override void Trace(TraceEvent traceEvent)
    {
        _traces.Add(traceEvent);
    }

    public List<TraceEvent> Traces => _traces;
}

我有同样的问题,并使用 DEBUG 标志仅在调试时启动 RunOnStartup:

        public static void Run(
            [TimerTrigger("* 0 7 * * 1-5"
#if DEBUG
            , RunOnStartup=true
#endif
            )]TimerInfo myTimer, TraceWriter log)
        {

只需在同一个 class 中添加另一个具有 HTTP 触发器类型的函数,添加您的代码,或从该函数调用您的 运行 方法并从您的浏览器调用它。

确保 comment/remove 在部署到产品时该函数,否则您将能够通过产品中的 HTTP 调用触发该函数。

来自https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=windows%2Ccsharp%2Cbash#non-http-triggered-functions

Non-HTTP triggered functions

For all kinds of functions other than HTTP triggers and webhooks, you can test your functions locally by calling an administration endpoint. Calling this endpoint with an HTTP POST request on the local server triggers the function. You can optionally pass test data to the execution in the body of the POST request. This functionality is similar to the Test tab in the Azure portal.

You call the following administrator endpoint to trigger non-HTTP functions:

http://localhost:{port}/admin/functions/{function_name}

To pass test data to the administrator endpoint of a function, you must supply the data in the body of a POST request message. The message body is required to have the following JSON format:

{
    "input": "<trigger_input>"
}

如果您使用的是 VS Code,请使用 Azure Functions extension:

  1. 按 F5 键进入调试模式,这将启动功能应用程序。
  2. 转到 Activity 栏中的 Azure 图标。
  3. Local Project下,找到你要运行的功能,右击,select "Execute Function Now".

查看此 MS quickstart guide

使用 postman 应该可以解决问题。按照以下步骤 运行 或在本地调试定时器触发器。

1。 运行 你的项目。

  1. 打开 Postman 并通过此 url http://localhost:{port}/admin/functions/{function_name}

  2. 确保使用 POST 方法和 Json 主体 { “输入”: ”” }

  3. 按发送。

您应该收到 202 的响应。

使用此 curl 命令启动您的函数

curl --request POST -H "Content-Type:application/json" --data '{"input":""}'  http://localhost:7071/admin/functions/{function_name}

需要输入数据,没有它函数将不会被触发。

另一种方法是手动触发 Postman 的功能:
Manually run a non HTTP-triggered function.

POST /admin/functions/<function name> HTTP/1.1
Host: localhost:<port>
Content-Type: application/json

{}

对我来说,它看起来像邮递员上的一个名为 Function1timerTrigger 函数: