Azure webjob 似乎不尊重 MaxDequeueCount 属性

Posted

技术标签:

【中文标题】Azure webjob 似乎不尊重 MaxDequeueCount 属性【英文标题】:Azure webjob not appearing to respect MaxDequeueCount property 【发布时间】:2017-07-04 17:52:35 【问题描述】:

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

在将队列消息发送到某个队列之前的最大重试次数 中毒队列(默认为 5)。

但我没有看到这种行为。在我的网络作业中,我有:

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):

在第 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 的消息。它多次出现的事实告诉我原始队列中的消息失败不正确

【问题讨论】:

你是在 Azure 上运行还是在本地运行? @Rob 在 Azure 上运行。 我们也在做同样的事情,如果你降级到 7.2.1 这个问题不会发生。然而,降级是一个糟糕的解决方案。对我们来说这不起作用,因为我们使用 Umbraco,它需要更高版本作为 nuget.org/packages/UmbracoFileSystemProviders.Azure 的一部分,您可以在依赖项 WindowsAzure.Storage (>= 8.7.0) nuget.org/packages/WindowsAzure.Storage 中看到它 【参考方案1】:

正如 Rob W 所述,使用 WindowsAzure.Storage > 7.1.2 时存在此问题。该问题显然已在 issue #1141 中修复,但尚未发布。

贡献者asifferman 在issue #985 上分享了@98​​7654323@。这似乎可以解决问题(它对我来说非常有效)。

如果链接失效,并且为了满足 SO 规则,这里是帖子以及代码 sn-p:

对于那些(像我一样)迫不及待想要获得下一个版本的人 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】:

如果您仍在寻找答案,我们尝试了列出的一些答案,但均未成功。事实证明,这是 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

【讨论】:

成功了!完美地描述了它。 也面临类似的问题,但最大出队计数对我们来说效果很好。在 x 出列计数后,消息会正确移动到毒队列。但在那之后,我们每 10 分钟就会在毒物队列中看到同一消息的一个新条目。问题似乎只发生在 WebJobs SDK 1.1.2 和 Azure Storage V8.0.1(这是我们的例子)问题被引用 @github.com/Azure/azure-webjobs-sdk/issues/985 我们可能会在它修复后降级......【参考方案3】:

如果我对其进行配置,MaxDequeueCount 属性对我来说可以正常工作。

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

我们也可以使用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");
            
        

日志信息请参考截图

【讨论】:

【参考方案4】:

我怀疑这是因为您实际上并没有运行您认为自己在 Azure 中的二进制文件。这也让我陷入了困境。

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

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

WebJob 被复制到 %TEMP%\jobsjob 下的临时目录 typejob namerandom name 并从那里运行这个选项 防止原始 WebJob 二进制文件被锁定,这可能 导致重新部署 WebJob 的问题。例如更新 .exe 文件 当前正在运行。

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

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

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

    FTP 到您的 Web 应用程序。浏览到包含您的 WebJob 代码的目录,然后将其删除。它应该在 /app_data/jobs/triggered/[your webjob name] 下。

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

    从 Visual Studio 发布我的新 WebJob。

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

【讨论】:

我想我以前见过这种行为。但是,我确实会在发布后立即定期验证我的 webjob 的运行状态,并且在所有情况下,作业都会重新启动。无论如何,我已经看到这个问题很长一段时间了,但巧合的是(出于其他原因)前几天我进入 Azure 门户,删除了与该网站关联的 webjobs,删除了 wwwroot 的内容,然后做了完全重新部署...我刚刚发现的东西-在某些情况下,我会重试> 5次。所以我不明白这个数字是如何确定的。 您是否正在运行多个 WebJob 实例? 没有网站(因此 webjob)是单个实例(并且 BatchSize=1)。但是 webjobs sdk 保证如果 webjob 的多个实例正在运行,那么只有一个实例会从队列中选择一个给定的项目。顺便说一句,我刚刚添加了一些 add'l 日志记录来报告 MaxDequeueCount 属性的值,以验证它是我设置的值并且它没有被某种方式覆盖。 伙计们,如果你们可以一起获得一个 repro,请在我们的 repo 中记录一个错误github.com/Azure/azure-webjobs-sdk/issues。出队计数不应超过最大值 - 我还没有看到这种情况发生。 @matthewc 我想用尽可能多的建设性信息记录这个错误。您能否快速查看我在***.com/questions/42381354/… 的后续帖子,我在其中询问了我正在寻找的与网络作业相关的日志信息?【参考方案5】:

我看到了同样的情况,即消息超过了最大出队计数。我稍后会发布更多详细信息,但我也看到看起来非常大的数字最终进入了毒药队列。所以我怀疑它在 5 之后添加到毒物队列中,但尝试更多最终会在毒物队列中(数百个)。

【讨论】:

您是否偶然看到同一原始消息的多个有害消息? 是的。它仍在为相同的原始消息创建(多个)消息,但也将其放回标准队列中。所以它似乎正在正确地毒化,但没有从原始队列中删除。【参考方案6】:

对于使用 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

【讨论】:

以上是关于Azure webjob 似乎不尊重 MaxDequeueCount 属性的主要内容,如果未能解决你的问题,请参考以下文章

为啥我需要在 Azure 管理门户中而不是在我的 WebJob 的 App.config 中为 WebJobs 配置连接字符串?

Azure 触发的 Webjob - 检测 webjob 何时停止

命名空间“Microsoft.Azure.WebJobs”中不存在类型或命名空间名称“TableAttribute”

如何在不删除的情况下暂停 azure webjob?

.NET Core 中的 Azure WebJobs 使用 VS 2017 15.3

Azure WebJobs 连接字符串配置 (AzureWebJobsDashboard??)