【问题标题】:azure queue storage - putting a message back in the queue天蓝色队列存储 - 将消息放回队列中
【发布时间】:2020-06-23 16:41:27
【问题描述】:

我正在构建一个队列处理 web 作业以从队列中读取消息并使用数据从 blob 存储中检索报告 uri,然后将其作为电子邮件中的链接发送。我的流程运行良好,但我需要在特定时间窗口内发送电子邮件。

我有另一个进程 (webjob) 从 sql 后端检索此数据并将其放入电子邮件队列中。

此网络作业每 30 分钟运行一次,并且仅获取当天和当前时间的 2 小时窗口内的数据。所以我知道队列中的任何内容都适用于今天和“现在”后的 2 小时内。我将如何进一步缩小范围以从队列中读取数据,如果“电子邮件发送”时间设置为 19:00 而当前时间为 18:00,我可以将此消息放回队列中以读取它再稍后,下次应该更接近 19:00 时,我可以处理它并通过电子邮件发送出去。
时间不一定是准确的,所以即使它在 19:00 的 30 分钟内(或任何设置发送的时间)也可以处理。所以我有效地从队列中取出一个对象,检查它的时间,如果它不在分配的“电子邮件发送”时间的 30 分钟内,我将它放回队列中并再次处理

** 在我的网络作业中,我有一个“Functions”类,其中包含一个方法“ProcessQueueMessage”,只要将消息放入队列,就会触发该方法。

// This function will get triggered/executed when a new message is written 
    // on an Azure Queue called queue.
    public async Task ProcessQueueMessage([QueueTrigger("%reportgenerator%")] Data.Dto.Schedule.ScheduleDto schedule)
    {
        var reports = await this._scheduledReportGenerationService.GenerateScheduledEmails(schedule.ID);
    }

ScheduleDto 类将具有生成时间属性,我可以读取它并将其与当前时间进行比较,并且仅当它在我指定的“时间窗口”内时才进行处理。我将如何阻止队列消息在此处被删除,以便我可以重新处理它?

【问题讨论】:

  • 您使用的是 Azure 存储队列还是服务总线队列?
  • 另外,从您的问题中不清楚您是使用 2 个网络作业还是仅使用 1 个网络作业。一个小要求:请花点时间格式化您的问题,然后将其分成几段。读一大段很痛苦:)。
  • 我有 2 个网络作业,一个从后端获取“今天 2 小时内”的数据,创建任何指定的报告并将其放入 blob 存储中。另一个读取此数据,并通过电子邮件将 blob (pdf) 的 URI 发送出去。我正在使用 Azure 存储队列
  • 对格式缺失表示歉意 :-)

标签: c# azure azure-queues


【解决方案1】:

当您将消息添加到队列时,只需设置 initialVisibilityDelay 以便在最短处理时间之前不会看到消息。

CloudQueue queue = queueClient.GetQueueReference(queueName);
var msg = new CloudQueueMessage("Hello World!");
TimeSpan timeSpanDelay = GetEarliestProcessTime();
await queue.AddMessageAsync(msg, null, timeSpanDelay, null, null);

CloudQueue.AddMessage

【讨论】:

    【解决方案2】:

    因此,Azure 存储队列有一些东西可以帮助您解决这种情况:

    关于将消息放回队列中,您不必做任何特别的事情。这是存储队列提供的一项功能。当您将消息出队时(Azure 存储术语中的GET Message),该消息将在一定时间内变得不可见,如果未被出队的进程删除,它将再次变为可见,并且可以被另一个进程拾取。

    因此,当您将消息出列时,请检查时间,如果不是正确的时间,您什么也不做。但是,请确保在处理完邮件后,删除该邮件,否则将再次被拾取。

    您可以做的另一件事是,当您将消息出列并发现现在不是处理该消息的正确时间时,您更新该消息并将其可见性超时属性设置为一个值,该值将使该消息再次可见到处理时间。例如,您在 18:00 将消息出列,发现该消息需要在 19:00 处理。在这种情况下,您将更新消息并将其可见性超时设置为 50 分钟(或大于 30 分钟的值,因为 30 分钟是您的 Web 作业的计划)。这将确保当您的 Web 作业在 18:30 运行时,该消息不会被 Web 作业拾取,因为该消息只会在 18:50 可见。

    您可以在此处阅读有关更新消息的更多信息:https://docs.microsoft.com/en-us/rest/api/storageservices/update-message,以及在此处阅读有关出列消息的更多信息:https://docs.microsoft.com/en-us/rest/api/storageservices/get-messages

    更新

    我完全忘记了它在 WebJob 中,所以什么都不做实际上会删除该消息。我猜你有 2 个选项(有点重复 cmets 中提到的内容):

    1. 抛出异常而不是什么都不做。这将确保 WebJob 处理器不会删除该消息。我自己没有尝试过,但您也可以更新消息并将其可见性超时设置为更接近 WebJob 本身所需时间的值(然后引发异常)。不过,这是一种反模式。
    2. 您在队列中添加一条新消息,并将其初始可见性超时设置为更接近所需时间的值(这也包含在另一个答案中),然后删除此消息。

    【讨论】:

    • 我实际上并没有使用 GetMessage 来读取队列消息,在我的 WebJob 中,我有 host.RunAndBlock,然后在我的函数类中,我有一个方法 (ProcessQueueMessage),只要写入新消息就会触发w 队列,这是“默认”网络作业行为。这不是最佳做法吗?
    • 读取和删除(以及放入毒队列)似乎都是自动发生的,没有我的任何干预,我只是在检测到消息时处理它
    • @proteus:你是对的,在 WebJobs 下,功能正常完成时会自动删除消息。 Gaurav 则相反,也许他熟悉较低级别的队列存储 API。
    • 所以在我的场景中,读取和删除是一个自动过程,我将如何“重新排队”?
    • @proteus:抛出异常会导致项目返回队列,但您的情况似乎更复杂。
    【解决方案3】:

    当您在 Azure 存储队列中排队某个项目时,您可以向该项目添加额外的详细信息,这将导致该项目在可配置的持续时间内隐藏。如果您的批处理作业只能每两个小时运行一次,但您想延迟发送具有更细粒度时间控制的电子邮件,那么我建议两小时排队的批处理作业可以使用此“initialVisibilityDelay”功能。

    这是另一个描述 API 的 SO 问题。

    Azure storage queue message (show at specific time)

    【讨论】:

      猜你喜欢
      • 2013-11-08
      • 2021-01-08
      • 2021-01-26
      • 2021-10-21
      • 2013-11-12
      • 1970-01-01
      • 1970-01-01
      • 2021-07-17
      • 2012-10-08
      相关资源
      最近更新 更多