Azure webjob看起来不尊重MaxDequeueCount属性

时间:2017-02-15 21:07:53

标签: azure azure-web-sites azure-webjobs azure-webjobssdk

我有一个带有几个队列触发函数的Azure webjob。 https://docs.microsoft.com/en-us/azure/app-service-web/websites-dotnet-webjobs-sdk-storage-queues-how-to#config上的SDK文档将MaxDequeueCount属性定义为:

  

将队列消息发送到的最大重试次数   毒性队列(默认为5)。

但我没有看到这种行为。在我的webjob中我得到了:

JobHostConfiguration config = new JobHostConfiguration();
config.Queues.MaxDequeueCount = 1;
JobHost host = new JobHost(config);
host.RunAndBlock();

然后我有一个队列触发的函数,我抛出一个异常:

public void ProcessQueueMessage([QueueTrigger("azurewejobtestingqueue")] string item, TextWriter logger)
{
   if ( item == "exception" )
   {
      throw new Exception();
   }
}

查看webjobs仪表板,我看到SDK尝试了5次(默认为5次,如上所述):

Webjob failures shown on webjobs dashboard

并在第5次尝试之后将消息移动到毒性队列。我希望看到1次重试(或没有重试?)而不是5次。

更新:启用Web应用程序的详细日志记录,并选择将这些日志保存到Azure Blob容器中。找到一些与azure-jobs-host-archive容器中的问题相关的日志。这是一个示例,显示出队计数为96的项目:

{
  "Type": "FunctionCompleted",
  "EndTime": "2017-02-22T00:07:40.8133081+00:00",
  "Failure": {
    "ExceptionType": "Microsoft.Azure.WebJobs.Host.FunctionInvocationException",
    "ExceptionDetails": "Microsoft.Azure.WebJobs.Host.FunctionInvocationException: Exception while executing function: ItemProcessor.ProcessQueueMessage ---> MyApp.Exceptions.MySpecialAppExceptionType: Exception of type 'MyApp.Exceptions.MySpecialAppExceptionType' was thrown.
  },
  "ParameterLogs": {},
  "FunctionInstanceId": "1ffac7b0-1290-4343-8ee1-2af0d39ae2c9",
  "Function": {
    "Id": "MyApp.Processors.ItemProcessor.ProcessQueueMessage",
    "FullName": "MyApp.Processors.ItemProcessor.ProcessQueueMessage",
    "ShortName": "ItemProcessor.ProcessQueueMessage",
    "Parameters": [
      {
        "Type": "QueueTrigger",
        "AccountName": "MyStorageAccount",
        "QueueName": "stuff-processor",
        "Name": "sourceFeedItemQueueItem"
      },
      {
        "Type": "BindingData",
        "Name": "dequeueCount"
      },
      {
        "Type": "ParameterDescriptor",
        "Name": "logger"
      }
    ]
  },
  "Arguments": {
    "sourceFeedItemQueueItem": "{\"SourceFeedUpdateID\":437530,\"PodcastFeedID\":\"2d48D2sf2\"}",
    "dequeueCount": "96",
    "logger": null
  },
  "Reason": "AutomaticTrigger",
  "ReasonDetails": "New queue message detected on 'stuff-processor'.",
  "StartTime": "2017-02-22T00:07:40.6017341+00:00",
  "OutputBlob": {
    "ContainerName": "azure-webjobs-hosts",
    "BlobName": "output-logs/1ffd3c7b012c043438ed12af0d39ae2c9.txt"
  },
  "ParameterLogBlob": {
    "ContainerName": "azure-webjobs-hosts",
    "BlobName": "output-logs/1cf2c1b012sa0d3438ee12daf0d39ae2c9.params.txt"
  },
  "LogLevel": "Info",
  "HostInstanceId": "d1825bdb-d92a-4657-81a4-36253e01ea5e",
  "HostDisplayName": "ItemProcessor",
  "SharedQueueName": "azure-webjobs-host-490daea03c70316f8aa2509438afe8ef",
  "InstanceQueueName": "azure-webjobs-host-d18252sdbd92a4657d1a436253e01ea5e",
  "Heartbeat": {
    "SharedContainerName": "azure-webjobs-hosts",
    "SharedDirectoryName": "heartbeats/490baea03cfdfd0416f8aa25aqr438afe8ef",
    "InstanceBlobName": "zd1825bdbdsdgga465781a436q53e01ea5e",
    "ExpirationInSeconds": 45
  },
  "WebJobRunIdentifier": {
    "WebSiteName": "myappengine",
    "JobType": "Continuous",
    "JobName": "ItemProcessor",
    "RunId": ""
  }
}

我还在寻找的是日志,它会显示特定队列项的详细信息,其中处理成功(因此从队列中删除)或由于异常而失败并放置在毒性队列中。到目前为止,我还没有找到任何显示详细信息的日志。上面输出中引用的日志文件不包含此类数据。

更新2:看看我的毒药队列的状态,看起来它可能是一支冒烟的枪,但我太密集了,不能把2和2放在一起。查看下面队列的屏幕截图,您可以多次看到带有ID(左栏)431210的消息。多次出现的事实告诉我原始队列中的消息不正确

Poison queue

6 个答案:

答案 0 :(得分:6)

如果您仍在寻求答案,我们会尝试列出一些未成功的答案。事实证明,这是Storage sdk(WindowsAzure.Storage)和Webjob sdk(Microsoft.Azure.WebJobs)的版本问题。为了解决这个问题,我们最终不得不将我们的Storage sdk版本降级到7.2.1(我们最近升级到8.1.1)。根据下面的文章,工程师现在已经意识到了这些问题,并希望很快就能解决这个问题:

https://github.com/Azure/azure-webjobs-sdk/issues/1045

答案 1 :(得分:6)

正如Rob W所述,使用WindowsAzure.Storage>时会出现此问题。 7.1.2。 issue #1141显然已经解决了这个问题,但这还没有成为一个版本。

投稿人asiffermancode snippet in a comment post上分享了issue #985。这似乎解决了这个问题(这对我来说很完美)。

如果链接已损坏且符合SO规则,请在此处发布帖子以及代码段:

  

对于那些不能等待下一个版本的人(像我一样)来获得   WebJobs SDK可与最新版本的Azure存储配合使用,以及   根据@brettsam的解释,你可以简单地写一个自定义   CustomQueueProcessorFactory在中创建一个新的CloudQueueMessage   CopyMessageToPoisonQueueAsync。

namespace ConsoleApplication1
{
    using Microsoft.Azure.WebJobs.Host.Queues;
    using Microsoft.WindowsAzure.Storage.Queue;
    using System.Threading;
    using System.Threading.Tasks;

    public class CustomQueueProcessorFactory : IQueueProcessorFactory
    {
        public QueueProcessor Create(QueueProcessorFactoryContext context)
        {
            return new CustomQueueProcessor(context);
        }

        private class CustomQueueProcessor : QueueProcessor
        {
            public CustomQueueProcessor(QueueProcessorFactoryContext context)
                : base(context)
            {
            }

            protected override Task CopyMessageToPoisonQueueAsync(CloudQueueMessage message, CloudQueue poisonQueue, CancellationToken cancellationToken)
            {
                var newMessage = new CloudQueueMessage(message.Id, message.PopReceipt);
                newMessage.SetMessageContent(message.AsBytes);

                return base.CopyMessageToPoisonQueueAsync(newMessage, poisonQueue, cancellationToken);
            }
        }
    }
}
  

然后在您的Main中,您只需设置自定义队列处理器   工厂主管配置中的工厂:

var config = new JobHostConfiguration();
config.Queues.QueueProcessorFactory = new CustomQueueProcessorFactory();
  

我可以使用WindowsAzure.Storage 8.1.1和   Microsoft.Azure.WebJobs 2.0.0。希望有所帮助!

答案 2 :(得分:1)

如果我配置它,MaxDequeueCount属性可以正常工作。

因此它不适合你,这很奇怪。当我设置 config.Queues.MaxDequeueCount = 2;然后我得到了预期的结果,请参阅截图。

enter image description here

我们也可以使用dequeueCount来控制重试次数。以下是试用的演示代码。

public void ProcessQueueMessage([QueueTrigger("queue")] string item, int dequeueCount, TextWriter logger)
        {
            if (dequeueCount == 1)
            {
                if (item == "exception")
                {
                    throw new Exception();
                }
                logger.WriteLine($"NewMsge: {item}");
                Console.WriteLine($"NewMsge: {item}");
            }
        }

日志信息请参阅截图

enter image description here

答案 3 :(得分:0)

我怀疑是因为你实际上没有运行你认为自己在Azure中的二进制文件。这个也把我扔了一个循环。

当您在Azure上运行触发的WebJobs时,发布新版本的WebJob不会导致旧的触发WebJob立即卸载并启动新的WebJob。如果您查看WebJob日志,我怀疑您在重新发布时不会看到重新启动。

这是因为Kudu默认将所有WebJob文件复制到临时目录并执行它们。来自Kudu WebJob docs

  

将WebJob复制到%TEMP%\ jobs {job下的临时目录   输入{job name} {random name}并从那里运行此选项   防止原始WebJob二进制文件被锁定   导致重新部署WebJob的问题。例如,更新.exe文件   目前正在运行。

我确保新发布的触发WebJob实际运行的唯一成功是执行以下操作:

  1. 登录Kudu控制台。这是https://yourappname.scm.azurewebsites.net。您将使用登录Azure门户时所执行的相同凭据。

  2. 登录后,单击顶部的Process Explorer菜单选项。找到当前正在运行的WebJob进程并将其终止。

  3. FTP进入您的Web App。浏览到包含WebJob代码的目录,然后将其删除。它应该在/ app_data / jobs / triggered / [你的webjob名称]下。

  4. 然后我跳到门户网站,浏览托管WebJob的Web App管理刀片,单击WebJobs菜单选项,确认旧的WebJob不再存在。

  5. 从Visual Studio发布我的新WebJob。

  6. 这应该保证您正在运行您发布的代码。希望这可以帮助。

答案 4 :(得分:0)

我看到同样的事情,消息超过了最大出列计数。我会稍微发布一些细节,但我也看到了毒药队列中最后一个非常大的数字。所以我怀疑它是在5之后添加到毒物队列,但是尝试更多,最终在毒物队列中有很多(数百)。

答案 5 :(得分:0)

对于使用Azure WebJobs v3.x SDK的任何人:

在v3.x中,hosts.json不适用于WebJob

相反,版本3.x使用标准的ASP.NET Core API,因此您需要使用ConfigureWebJobs方法对其进行配置:

static async Task Main()
{
    var builder = new HostBuilder();
    builder.ConfigureWebJobs(b =>
    {
        b.AddAzureStorageCoreServices();
        b.AddAzureStorage(a => {
            a.BatchSize = 8;
            a.NewBatchThreshold = 4;
            a.MaxDequeueCount = 4;
            a.MaxPollingInterval = TimeSpan.FromSeconds(15);
        });
    });
    var host = builder.Build();
    using (host)
    {
        await host.RunAsync();
    }
}

文档:https://docs.microsoft.com/pt-pt/azure/app-service/webjobs-sdk-how-to#queue-storage-trigger-configuration