创建一个触发器来运行长时间执行的函数C#

时间:2018-02-08 09:42:17

标签: c# azure http triggers azure-functions

我有一个功能,假设每天早上12点运行并做一些工作 通常需要2个小时......

我想创建一个调用它的触发器。 所以我创建了一个带有时间触发器的Azure功能应用程序,它使用HTTP请求调用我的调用我的函数的控制器。

我为测试而创建的控制器功能。

  [HttpGet]
    public async Task<bool> updateFromRegAdmin() 
    {
        try
        {

           RegEditApi_Service.retrieveRegAdminApiCredentials();



            return true;
        }
        catch (Exception e)
        {
            Logger.writeToLog(Logger.LOG_SEVERITY_TYPE.Error, "", "updateFromRegAdmin ", e.Message);
            return false;
        }
    }

所以我说功能“retrieveRegAdminApiCredentials”运行2个小时。 问题是请求在几分钟后出现超时......

那么如何创建一个只触发内部函数并让它在后台运行的请求呢?

顺便说一下,如果没有HTTP请求,我无法在服务器上创建触发器,因为我公司在Azure上扩展了服务器(它将多次运行我的触发器并创建数据库副本)。

我之前的解决方案是......

 public class JobScheduler
{
    public static void Start()
    {
        IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
        scheduler.Start();

        IJobDetail job = JobBuilder.Create<GetExchangeRates>().Build();

        ITrigger trigger = TriggerBuilder.Create()
            .WithDailyTimeIntervalSchedule
              (s =>
                 s.WithIntervalInHours(24)
                .OnEveryDay()
                .StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(00, 00))
              )
            .Build();

        scheduler.ScheduleJob(job, trigger);


    }

} 

public class GetExchangeRates : IJob
{
    public void Execute(IJobExecutionContext context)
    {
       Random random = new Random();
        int randomNumber = random.Next(100000, 900000);

        Thread.Sleep(randomNumber);

        RegEditApi_Service.retrieveRegAdminApiCredentials();
    }
}

3 个答案:

答案 0 :(得分:0)

看起来您需要一个能够安排和执行任务队列的专用组件。有很好的框架,但如果您因为某种原因不喜欢它们,那么请确保启动/重用空闲线程并强制执行长期执行。因此,您的API将返回类似的内容:200,OK表示该过程已成功启动。

主要思想:明确区分你的线程。这实际上非常具有挑战性。

答案 1 :(得分:0)

默认情况下,Azure函数运行最多15分钟(可能是5,懒得现在检查文档:-))。

如果您的功能符合消费计划,则无法增加此时间。如果您在App Service计划中托管您的功能,则可以执行此操作。

答案 2 :(得分:0)

如果我理解正确的话,你所拥有的是一个Azure Function Timer触发器,它通过“RegEditApi_Service.retrieveRegAdminApiCredentials()”向你的服务器发送一个HTTP请求。

问题是,你的功能超时了。要解决此问题,您应该将HTTP端点置于“retrieveRegAdminApiCredentials()”后面,并在接受请求时立即返回。

如果您需要来自服务器的某些返回值,您应该让服务器在某个队列(如Azure存储队列)上放置一条消息,并让另一个Azure函数侦听此队列,并接受该消息。

如果长操作的结果相对较小,您可以在消息中得到结果。否则,你需要执行一些操作,但是这个操作应该更快,因为你已经执行了长时间运行的操作,并保留了答案,所以现在你只需要检索它,并可能做一些清理。

您还可以查看Azure Durable Functions,它适用于此用例,但仍在预览中,我不确定它会给您带来多少好处:

https://docs.microsoft.com/en-us/azure/azure-functions/durable-functions-overview#pattern-3-async-http-apis